blob: 99e45dc195dba0cc28f03157edf3df96024e8101 [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, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800135 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800136}
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, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800144 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145}
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) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800701 hdd_debug("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);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800713 hdd_debug("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 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800941#endif /* FEATURE_WLAN_EXTSCAN */
942
943#ifdef WLAN_FEATURE_LINK_LAYER_STATS
944 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
945 .vendor_id =
946 QCA_NL80211_VENDOR_ID,
947 .subcmd =
948 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
949 },
950 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
951 .vendor_id =
952 QCA_NL80211_VENDOR_ID,
953 .subcmd =
954 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
955 },
956 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
957 .vendor_id =
958 QCA_NL80211_VENDOR_ID,
959 .subcmd =
960 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
961 },
962 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
963 .vendor_id =
964 QCA_NL80211_VENDOR_ID,
965 .subcmd =
966 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
967 },
968 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
969 .vendor_id =
970 QCA_NL80211_VENDOR_ID,
971 .subcmd =
972 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
973 },
974 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
975 .vendor_id =
976 QCA_NL80211_VENDOR_ID,
977 .subcmd =
978 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
979 },
980#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
981 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
982 .vendor_id =
983 QCA_NL80211_VENDOR_ID,
984 .subcmd =
985 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
986 },
987 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
988 .vendor_id = QCA_NL80211_VENDOR_ID,
989 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
990 },
991#ifdef WLAN_FEATURE_ROAM_OFFLOAD
992 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
993 .vendor_id =
994 QCA_NL80211_VENDOR_ID,
995 .subcmd =
996 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
997 },
998#endif
999 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1000 .vendor_id =
1001 QCA_NL80211_VENDOR_ID,
1002 .subcmd =
1003 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1004 },
1005 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1006 .vendor_id =
1007 QCA_NL80211_VENDOR_ID,
1008 .subcmd =
1009 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1010 },
1011 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1012 .vendor_id =
1013 QCA_NL80211_VENDOR_ID,
1014 .subcmd =
1015 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1016 },
1017 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1018 .vendor_id =
1019 QCA_NL80211_VENDOR_ID,
1020 .subcmd =
1021 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1022 },
1023 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1024 .vendor_id =
1025 QCA_NL80211_VENDOR_ID,
1026 .subcmd =
1027 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1028 },
1029#ifdef FEATURE_WLAN_EXTSCAN
1030 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1031 .vendor_id = QCA_NL80211_VENDOR_ID,
1032 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1033 },
1034 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1035 .vendor_id = QCA_NL80211_VENDOR_ID,
1036 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1037 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001038 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1039 .vendor_id = QCA_NL80211_VENDOR_ID,
1040 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1041 },
1042#endif /* FEATURE_WLAN_EXTSCAN */
1043 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1046 },
1047#ifdef WLAN_FEATURE_MEMDUMP
1048 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1051 },
1052#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001053#ifdef WLAN_FEATURE_TSF
1054 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1055 .vendor_id = QCA_NL80211_VENDOR_ID,
1056 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1057 },
1058#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001059 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1060 .vendor_id = QCA_NL80211_VENDOR_ID,
1061 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1062 },
1063 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1064 .vendor_id = QCA_NL80211_VENDOR_ID,
1065 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1066 },
1067 /* OCB events */
1068 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1069 .vendor_id = QCA_NL80211_VENDOR_ID,
1070 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1071 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001072#ifdef FEATURE_LFR_SUBNET_DETECTION
1073 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1076 },
1077#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001078
1079#ifdef WLAN_FEATURE_NAN_DATAPATH
1080 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1083 },
1084#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001085
1086 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1087 .vendor_id = QCA_NL80211_VENDOR_ID,
1088 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1089 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301090 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1091 .vendor_id = QCA_NL80211_VENDOR_ID,
1092 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1093 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301094 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1095 .vendor_id = QCA_NL80211_VENDOR_ID,
1096 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1097 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001098#ifdef WLAN_UMAC_CONVERGENCE
1099 COMMON_VENDOR_EVENTS
1100#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101};
1102
1103/**
1104 * __is_driver_dfs_capable() - get driver DFS capability
1105 * @wiphy: pointer to wireless wiphy structure.
1106 * @wdev: pointer to wireless_dev structure.
1107 * @data: Pointer to the data to be passed via vendor interface
1108 * @data_len:Length of the data to be passed
1109 *
1110 * This function is called by userspace to indicate whether or not
1111 * the driver supports DFS offload.
1112 *
1113 * Return: 0 on success, negative errno on failure
1114 */
1115static int __is_driver_dfs_capable(struct wiphy *wiphy,
1116 struct wireless_dev *wdev,
1117 const void *data,
1118 int data_len)
1119{
1120 u32 dfs_capability = 0;
1121 struct sk_buff *temp_skbuff;
1122 int ret_val;
1123 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1124
Jeff Johnson1f61b612016-02-12 16:28:33 -08001125 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126
1127 ret_val = wlan_hdd_validate_context(hdd_ctx);
1128 if (ret_val)
1129 return ret_val;
1130
Anurag Chouhan6d760662016-02-20 16:05:43 +05301131 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 hdd_err("Command not allowed in FTM mode");
1133 return -EPERM;
1134 }
1135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137
1138 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1139 NLMSG_HDRLEN);
1140
1141 if (temp_skbuff != NULL) {
1142 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1143 dfs_capability);
1144 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001145 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 kfree_skb(temp_skbuff);
1147
1148 return ret_val;
1149 }
1150
1151 return cfg80211_vendor_cmd_reply(temp_skbuff);
1152 }
1153
Jeff Johnson020db452016-06-29 14:37:26 -07001154 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 return -ENOMEM;
1156}
1157
1158/**
1159 * is_driver_dfs_capable() - get driver DFS capability
1160 * @wiphy: pointer to wireless wiphy structure.
1161 * @wdev: pointer to wireless_dev structure.
1162 * @data: Pointer to the data to be passed via vendor interface
1163 * @data_len:Length of the data to be passed
1164 *
1165 * This function is called by userspace to indicate whether or not
1166 * the driver supports DFS offload. This is an SSR-protected
1167 * wrapper function.
1168 *
1169 * Return: 0 on success, negative errno on failure
1170 */
1171static int is_driver_dfs_capable(struct wiphy *wiphy,
1172 struct wireless_dev *wdev,
1173 const void *data,
1174 int data_len)
1175{
1176 int ret;
1177
1178 cds_ssr_protect(__func__);
1179 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1180 cds_ssr_unprotect(__func__);
1181
1182 return ret;
1183}
1184
1185/**
1186 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1187 *
1188 * @adapter: SAP adapter pointer
1189 *
1190 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1191 * radio. So in case of DFS MCC scenario override current SAP given config
1192 * to follow concurrent SAP DFS config
1193 *
1194 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1195 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1197{
1198 hdd_adapter_t *con_sap_adapter;
1199 tsap_Config_t *sap_config, *con_sap_config;
1200 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001201 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001202
1203 /*
1204 * Check if AP+AP case, once primary AP chooses a DFS
1205 * channel secondary AP should always follow primary APs channel
1206 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001207 if (!policy_mgr_concurrent_beaconing_sessions_running(
1208 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001209 return 0;
1210
1211 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1212 if (!con_sap_adapter)
1213 return 0;
1214
1215 sap_config = &adapter->sessionCtx.ap.sapConfig;
1216 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1217 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1218
1219 if (!CDS_IS_DFS_CH(con_ch))
1220 return 0;
1221
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001222 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001224 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 sap_config->channel = con_ch;
1226
1227 if (con_sap_config->acs_cfg.acs_mode == true) {
1228 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1229 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001230 hdd_err("Primary AP channel config error");
1231 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 con_ch, con_sap_config->acs_cfg.pri_ch,
1233 con_sap_config->acs_cfg.ht_sec_ch);
1234 return -EINVAL;
1235 }
1236 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1237 * MCC restriction. So free ch list allocated in do_acs
1238 * func for Sec AP and realloc for Pri AP ch list size
1239 */
1240 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301241 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301243 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001244 &con_sap_config->acs_cfg,
1245 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301246 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001247 sizeof(uint8_t) *
1248 con_sap_config->acs_cfg.ch_list_count);
1249 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001250 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001251 return -ENOMEM;
1252 }
1253
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 con_sap_config->acs_cfg.ch_list,
1256 con_sap_config->acs_cfg.ch_list_count);
1257
1258 } else {
1259 sap_config->acs_cfg.pri_ch = con_ch;
1260 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1261 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1262 }
1263
1264 return con_ch;
1265}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001266
1267/**
1268 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1269 * @sap_cfg: pointer to SAP config struct
1270 *
1271 * This function sets the default ACS start and end channel for the given band
1272 * and also parses the given ACS channel list.
1273 *
1274 * Return: None
1275 */
1276
1277static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1278 bool vht_enabled)
1279{
1280 int i;
1281 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1282 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001283 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1284 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001285 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1286 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001287 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1288 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001291 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1292 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001295 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1296 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 }
1298
1299 if (ht_enabled)
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1301
1302 if (vht_enabled)
1303 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1304
1305
1306 /* Parse ACS Chan list from hostapd */
1307 if (!sap_cfg->acs_cfg.ch_list)
1308 return;
1309
1310 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1311 sap_cfg->acs_cfg.end_ch =
1312 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1313 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301314 /* avoid channel as start channel */
1315 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1316 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001317 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1318 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1319 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1320 }
1321}
1322
1323
1324static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1325
1326/**
1327 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1328 * @adapter: pointer to SAP adapter struct
1329 *
1330 * This function starts the ACS procedure if there are no
1331 * constraints like MBSSID DFS restrictions.
1332 *
1333 * Return: Status of ACS Start procedure
1334 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301335int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336{
1337
1338 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1339 tsap_Config_t *sap_config;
1340 tpWLAN_SAPEventCB acs_event_callback;
1341 int status;
1342
1343 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301344 if (hdd_ctx->acs_policy.acs_channel)
1345 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1346 else
1347 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001348
1349 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001350 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001351 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001352
1353 if (status > 0) {
1354 /*notify hostapd about channel override */
1355 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1356 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1357 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358 }
Jeff Johnson68755312017-02-10 11:46:55 -08001359
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001360 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1361 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001362 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001363 return -EINVAL;
1364 }
1365
1366 acs_event_callback = hdd_hostapd_sap_event_cb;
1367
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301368 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301369 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301370 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 acs_event_callback, sap_config, adapter->dev);
1374
1375
1376 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001377 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 return -EINVAL;
1379 }
bings394afdd2017-01-09 11:22:38 +08001380 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1381 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1383
1384 return 0;
1385}
1386
1387/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301388 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1389 * @ap_adapter: AP adapter
1390 * @nol: Non-occupancy list
1391 * @nol_len: Length of NOL
1392 *
1393 * Get the NOL for SAP
1394 *
1395 * Return: Zero on success, non-zero on failure
1396 */
1397static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1398 uint32_t *nol_len)
1399{
1400 QDF_STATUS ret;
1401
1402 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1403 nol, nol_len);
1404 if (QDF_IS_STATUS_ERROR(ret))
1405 return -EINVAL;
1406
1407 return 0;
1408}
1409
1410/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301411 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1412 * @hdd_ctx: hdd context
1413 * @acs_chan_params: external acs channel params
1414 * @sap_config: SAP config
1415 *
1416 * This API provides unsorted pcl list.
1417 * this list is a subset of the valid channel list given by hostapd.
1418 * if channel is not present in pcl, weightage will be given as zero
1419 *
1420 * Return: Zero on success, non-zero on failure
1421 */
1422static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1423 struct hdd_vendor_acs_chan_params *acs_chan_params,
1424 tsap_Config_t *sap_config)
1425{
1426 int i, j;
1427
1428 for (i = 0; i < acs_chan_params->channel_count; i++) {
1429 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1430 if (acs_chan_params->channel_list[i] ==
1431 sap_config->acs_cfg.pcl_channels[j]) {
1432 acs_chan_params->vendor_pcl_list[i] =
1433 sap_config->acs_cfg.pcl_channels[j];
1434 acs_chan_params->vendor_weight_list[i] =
1435 sap_config->acs_cfg.
1436 pcl_channels_weight_list[j];
1437 break;
1438 } else {
1439 acs_chan_params->vendor_pcl_list[i] =
1440 acs_chan_params->channel_list[i];
1441 acs_chan_params->vendor_weight_list[i] = 0;
1442 }
1443 }
1444 }
1445 if (hdd_ctx->unsafe_channel_count == 0)
1446 return;
1447 /* Update unsafe channel weight as zero */
1448 for (i = 0; i < acs_chan_params->channel_count; i++) {
1449 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1450 if (acs_chan_params->channel_list[i] ==
1451 hdd_ctx->unsafe_channel_list[j]) {
1452 acs_chan_params->vendor_weight_list[i] = 0;
1453 }
1454 }
1455 }
1456}
1457
1458/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301459 * hdd_update_reg_chan_info : This API contructs channel info
1460 * for all the given channel
1461 * @adapter: pointer to SAP adapter struct
1462 * @channel_count: channel count
1463 * @channel_list: channel list
1464 *
1465 * Return: Status of of channel information updation
1466 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301467static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301468 uint32_t channel_count,
1469 uint8_t *channel_list)
1470{
1471 int i;
1472 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001473 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301474 uint8_t bw_offset = 0, chan = 0;
1475 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1476 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1477
1478 /* memory allocation */
1479 sap_config->channel_info = qdf_mem_malloc(
1480 sizeof(struct hdd_channel_info) *
1481 channel_count);
1482 if (!sap_config->channel_info) {
1483 hdd_err("memory allocation failed");
1484 return -ENOMEM;
1485
1486 }
1487 for (i = 0; i < channel_count; i++) {
1488 icv = &sap_config->channel_info[i];
1489 chan = channel_list[i];
1490
1491 if (chan == 0)
1492 continue;
1493
1494 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1495 bw_offset = 1 << BW_40_OFFSET_BIT;
1496 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1497 bw_offset = 1 << BW_20_OFFSET_BIT;
1498 icv->freq = cds_get_channel_freq(chan);
1499 icv->ieee_chan_number = chan;
1500 icv->max_reg_power = cds_get_channel_reg_power(chan);
1501
1502 /* filling demo values */
1503 icv->max_radio_power = HDD_MAX_TX_POWER;
1504 icv->min_radio_power = HDD_MIN_TX_POWER;
1505 /* not supported in current driver */
1506 icv->max_antenna_gain = 0;
1507
1508 icv->reg_class_id = wlan_hdd_find_opclass(
1509 WLAN_HDD_GET_HAL_CTX(adapter),
1510 chan, bw_offset);
1511
1512 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1513 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1514 cds_set_channel_params(chan, 0, &ch_params);
1515 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1516 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1517 }
1518 icv->flags = 0;
1519 icv->flags = cds_get_vendor_reg_flags(chan,
1520 sap_config->acs_cfg.ch_width,
1521 sap_config->acs_cfg.is_ht_enabled,
1522 sap_config->acs_cfg.is_vht_enabled,
1523 hdd_ctx->config->enable_sub_20_channel_width);
1524
1525 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1526 icv->freq, icv->flags,
1527 icv->flagext, icv->ieee_chan_number,
1528 icv->max_reg_power, icv->max_radio_power,
1529 icv->min_radio_power, icv->reg_class_id,
1530 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1531 icv->vht_center_freq_seg1);
1532 }
1533 return 0;
1534}
1535
1536/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1537#define CHAN_INFO_ATTR_FLAGS \
1538 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1539#define CHAN_INFO_ATTR_FLAG_EXT \
1540 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1541#define CHAN_INFO_ATTR_FREQ \
1542 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1543#define CHAN_INFO_ATTR_MAX_REG_POWER \
1544 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1545#define CHAN_INFO_ATTR_MAX_POWER \
1546 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1547#define CHAN_INFO_ATTR_MIN_POWER \
1548 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1549#define CHAN_INFO_ATTR_REG_CLASS_ID \
1550 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1551#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1552 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1553#define CHAN_INFO_ATTR_VHT_SEG_0 \
1554 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1555#define CHAN_INFO_ATTR_VHT_SEG_1 \
1556 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1557
1558/**
1559 * hdd_cfg80211_update_channel_info() - add channel info attributes
1560 * @skb: pointer to sk buff
1561 * @hdd_ctx: pointer to hdd station context
1562 * @idx: attribute index
1563 *
1564 * Return: Success(0) or reason code for failure
1565 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301566static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301567hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1568 tsap_Config_t *sap_config, int idx)
1569{
1570 struct nlattr *nla_attr, *channel;
1571 struct hdd_channel_info *icv;
1572 int i;
1573
1574 nla_attr = nla_nest_start(skb, idx);
1575 if (!nla_attr)
1576 goto fail;
1577
1578 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1579 channel = nla_nest_start(skb, i);
1580 if (!channel)
1581 goto fail;
1582
1583 icv = &sap_config->channel_info[i];
1584 if (!icv) {
1585 hdd_err("channel info not found");
1586 goto fail;
1587 }
1588 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1589 icv->freq) ||
1590 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1591 icv->flags) ||
1592 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1593 icv->flagext) ||
1594 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1595 icv->max_reg_power) ||
1596 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1597 icv->max_radio_power) ||
1598 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1599 icv->min_radio_power) ||
1600 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1601 icv->reg_class_id) ||
1602 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1603 icv->max_antenna_gain) ||
1604 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1605 icv->vht_center_freq_seg0) ||
1606 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1607 icv->vht_center_freq_seg1)) {
1608 hdd_err("put fail");
1609 goto fail;
1610 }
1611 nla_nest_end(skb, channel);
1612 }
1613 nla_nest_end(skb, nla_attr);
1614 return 0;
1615fail:
1616 hdd_err("nl channel update failed");
1617 return -EINVAL;
1618}
1619#undef CHAN_INFO_ATTR_FLAGS
1620#undef CHAN_INFO_ATTR_FLAG_EXT
1621#undef CHAN_INFO_ATTR_FREQ
1622#undef CHAN_INFO_ATTR_MAX_REG_POWER
1623#undef CHAN_INFO_ATTR_MAX_POWER
1624#undef CHAN_INFO_ATTR_MIN_POWER
1625#undef CHAN_INFO_ATTR_REG_CLASS_ID
1626#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1627#undef CHAN_INFO_ATTR_VHT_SEG_0
1628#undef CHAN_INFO_ATTR_VHT_SEG_1
1629
1630/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301631 * hdd_cfg80211_update_pcl() - add pcl info attributes
1632 * @skb: pointer to sk buff
1633 * @hdd_ctx: pointer to hdd station context
1634 * @idx: attribute index
1635 * @vendor_pcl_list: PCL list
1636 * @vendor_weight_list: PCL weights
1637 *
1638 * Return: Success(0) or reason code for failure
1639 */
1640static int32_t
1641hdd_cfg80211_update_pcl(struct sk_buff *skb,
1642 uint8_t ch_list_count, int idx,
1643 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1644{
1645 struct nlattr *nla_attr, *channel;
1646 int i;
1647
1648 nla_attr = nla_nest_start(skb, idx);
1649
1650 if (!nla_attr)
1651 goto fail;
1652
1653 for (i = 0; i < ch_list_count; i++) {
1654 channel = nla_nest_start(skb, i);
1655 if (!channel)
1656 goto fail;
1657 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1658 vendor_pcl_list[i]) ||
1659 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1660 vendor_weight_list[i])) {
1661 hdd_err("put fail");
1662 goto fail;
1663 }
1664 nla_nest_end(skb, channel);
1665 }
1666 nla_nest_end(skb, nla_attr);
1667
1668 return 0;
1669fail:
1670 hdd_err("updating pcl list failed");
1671 return -EINVAL;
1672}
1673
1674static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1675{
1676 /* Get scan band */
1677 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1678 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1679 *band = eCSR_BAND_24;
1680 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1681 *band = eCSR_BAND_5G;
1682 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1683 *band = eCSR_BAND_ALL;
1684 }
1685 /* Auto is not supported currently */
1686 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1687 hdd_err("invalid band");
1688 *band = eCSR_BAND_24;
1689 }
1690}
1691
1692void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1693 uint8_t reason)
1694{
1695 struct sk_buff *skb;
1696 tsap_Config_t *sap_config;
1697 uint32_t channel_count = 0, status;
1698 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1699 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1700 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1701 struct hdd_vendor_acs_chan_params acs_chan_params;
1702 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1703 eCsrBand band = eCSR_BAND_24;
1704 eCsrPhyMode phy_mode;
1705
1706 if (!hdd_ctx) {
1707 hdd_err("HDD context is NULL");
1708 return;
1709 }
1710
1711 ENTER();
1712 sap_config = &adapter->sessionCtx.ap.sapConfig;
1713
1714 /* Get valid channels for SAP */
1715 wlan_hdd_sap_get_valid_channellist(adapter,
1716 &channel_count, channel_list);
1717
1718 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1719 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1720 /* Get phymode */
1721 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1722
1723 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1724 &(adapter->wdev),
1725 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1726 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1727 GFP_KERNEL);
1728
1729 if (!skb) {
1730 hdd_err("cfg80211_vendor_event_alloc failed");
1731 return;
1732 }
1733 /*
1734 * Application expects pcl to be a subset of channel list
1735 * Remove all channels which are not in channel list from pcl
1736 * and add weight as zero
1737 */
1738 acs_chan_params.channel_count = channel_count;
1739 acs_chan_params.channel_list = channel_list;
1740 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1741 acs_chan_params.vendor_weight_list = vendor_weight_list;
1742
1743 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1744 sap_config);
1745 /* Update values in NL buffer */
1746 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1747 reason) ||
1748 nla_put_u8(skb,
1749 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1750 false) ||
1751 nla_put_u8(skb,
1752 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1753 true) ||
1754 nla_put_u8(skb,
1755 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1756 true) ||
1757 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1758 sap_config->acs_cfg.ch_width) ||
1759 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1760 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1761 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1762 band) ||
1763 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1764 phy_mode) ||
1765 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1766 channel_count, channel_list)) {
1767 hdd_err("nla put fail");
1768 goto fail;
1769 }
1770 status = hdd_cfg80211_update_pcl(skb, channel_count,
1771 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1772 vendor_pcl_list, vendor_weight_list);
1773
1774 if (status != 0)
1775 goto fail;
1776
1777 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1778 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1779
1780 if (status != 0)
1781 goto fail;
1782
1783 cfg80211_vendor_event(skb, GFP_KERNEL);
1784 return;
1785fail:
1786 if (skb)
1787 kfree_skb(skb);
1788}
1789
1790static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1791{
1792 struct hdd_external_acs_timer_context *timer_context;
1793
1794 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1795 return 0;
1796
1797 hdd_notice("Starting vendor app based ACS");
1798 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1799 timer_context->adapter = adapter;
1800
1801 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1802 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1803 QDF_TIMER_TYPE_SW,
1804 hdd_acs_response_timeout_handler, timer_context);
1805 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1806 return 0;
1807}
1808
1809/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1811 * @wiphy: Linux wiphy struct pointer
1812 * @wdev: Linux wireless device struct pointer
1813 * @data: ACS information from hostapd
1814 * @data_len: ACS information length
1815 *
1816 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1817 * and starts ACS procedure.
1818 *
1819 * Return: ACS procedure start status
1820 */
1821
1822static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1823 struct wireless_dev *wdev,
1824 const void *data, int data_len)
1825{
1826 struct net_device *ndev = wdev->netdev;
1827 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1828 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1829 tsap_Config_t *sap_config;
1830 struct sk_buff *temp_skbuff;
1831 int status = -EINVAL, i = 0;
1832 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1833 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301834 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001835
1836 /* ***Note*** Donot set SME config related to ACS operation here because
1837 * ACS operation is not synchronouse and ACS for Second AP may come when
1838 * ACS operation for first AP is going on. So only do_acs is split to
1839 * seperate start_acs routine. Also SME-PMAC struct that is used to
1840 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1841 * config shall be set only from start_acs.
1842 */
1843
1844 /* nla_policy Policy template. Policy not applied as some attributes are
1845 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1846 *
1847 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1848 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1849 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1850 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1851 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1852 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1853 */
1854
Jeff Johnson1f61b612016-02-12 16:28:33 -08001855 ENTER_DEV(ndev);
1856
Anurag Chouhan6d760662016-02-20 16:05:43 +05301857 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858 hdd_err("Command not allowed in FTM mode");
1859 return -EPERM;
1860 }
1861
Kapil Gupta8878ad92017-02-13 11:56:04 +05301862 if (hdd_ctx->config->force_sap_acs &&
1863 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001864 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001865 return -EPERM;
1866 }
1867
1868 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301869 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001870 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301871
Naveen Rawat64e477e2016-05-20 10:34:56 -07001872 if (cds_is_sub_20_mhz_enabled()) {
1873 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1874 status = -EINVAL;
1875 goto out;
1876 }
1877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301879 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880
1881 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1882 NULL);
1883 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001884 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 goto out;
1886 }
1887
1888 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001889 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 goto out;
1891 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301892 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1893 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894
1895 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1896 ht_enabled =
1897 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1898 else
1899 ht_enabled = 0;
1900
1901 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1902 ht40_enabled =
1903 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1904 else
1905 ht40_enabled = 0;
1906
1907 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1908 vht_enabled =
1909 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1910 else
1911 vht_enabled = 0;
1912
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301913 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1914 vht_enabled = 0;
1915 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1916 }
1917
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1919 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1920 } else {
1921 if (ht_enabled && ht40_enabled)
1922 ch_width = 40;
1923 else
1924 ch_width = 20;
1925 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301926
1927 /* this may be possible, when sap_force_11n_for_11ac is set */
1928 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1929 if (ht_enabled && ht40_enabled)
1930 ch_width = 40;
1931 else
1932 ch_width = 20;
1933 }
1934
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001935 if (ch_width == 80)
1936 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1937 else if (ch_width == 40)
1938 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1939 else
1940 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1941
1942 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1943 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1944 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1945 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1946 * since it contains the frequency values of the channels in
1947 * the channel list.
1948 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1949 * is present
1950 */
1951 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1952 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1953 sap_config->acs_cfg.ch_list_count = nla_len(
1954 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1955 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301956 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 sizeof(uint8_t) *
1958 sap_config->acs_cfg.ch_list_count);
1959 if (sap_config->acs_cfg.ch_list == NULL)
1960 goto out;
1961
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301962 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 sap_config->acs_cfg.ch_list_count);
1964 }
1965 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1966 uint32_t *freq =
1967 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1968 sap_config->acs_cfg.ch_list_count = nla_len(
1969 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1970 sizeof(uint32_t);
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 sap_config->acs_cfg.ch_list_count);
1974 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001975 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976 status = -ENOMEM;
1977 goto out;
1978 }
1979
1980 /* convert frequency to channel */
1981 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1982 sap_config->acs_cfg.ch_list[i] =
1983 ieee80211_frequency_to_channel(freq[i]);
1984 }
1985 }
1986
1987 hdd_debug("get pcl for DO_ACS vendor command");
1988
1989 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001990 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301991 sap_config->acs_cfg.pcl_channels,
1992 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301993 sap_config->acs_cfg.pcl_channels_weight_list,
1994 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301995 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001996 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301999 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2000 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002001 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002002 vht_enabled = 1;
2003 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2004 sap_config->acs_cfg.ch_width =
2005 hdd_ctx->config->vhtChannelWidth;
2006 /* No VHT80 in 2.4G so perform ACS accordingly */
2007 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302008 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302010 ch_width = 40;
2011 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012 }
2013
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302014 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2015
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002016 hdd_debug("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2018 ch_width, ht_enabled, vht_enabled,
2019 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2020
Kapil Gupta8878ad92017-02-13 11:56:04 +05302021 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2022 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2023
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002024 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002025 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002026 sap_config->acs_cfg.ch_list_count);
2027 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002028 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002029 }
2030 sap_config->acs_cfg.acs_mode = true;
2031 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002032 /* ***Note*** Completion variable usage is not allowed
2033 * here since ACS scan operation may take max 2.2 sec
2034 * for 5G band:
2035 * 9 Active channel X 40 ms active scan time +
2036 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2038 * for this long. So we split up the scanning part.
2039 */
2040 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002041 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042 status = 0;
2043 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302044 /* Check if vendor specific acs is enabled */
2045 if (hdd_ctx->config->vendor_acs_support) {
2046 sap_config->acs_cfg.hw_mode = hw_mode;
2047 hdd_create_acs_timer(adapter);
2048 hdd_update_acs_timer_reason(adapter,
2049 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2050 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2051 wlan_sap_set_vendor_acs(
2052 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2053 true);
2054 else
2055 wlan_sap_set_vendor_acs(
2056 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2057 false);
2058
2059 } else
2060 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002061 }
2062
2063out:
2064 if (0 == status) {
2065 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2066 NLMSG_HDRLEN);
2067 if (temp_skbuff != NULL)
2068 return cfg80211_vendor_cmd_reply(temp_skbuff);
2069 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002070 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2072
2073 return status;
2074}
2075
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002076/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002077 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2078 * @wiphy: Linux wiphy struct pointer
2079 * @wdev: Linux wireless device struct pointer
2080 * @data: ACS information from hostapd
2081 * @data_len: ACS information len
2082 *
2083 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2084 * and starts ACS procedure.
2085 *
2086 * Return: ACS procedure start status
2087 */
2088
2089static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2090 struct wireless_dev *wdev,
2091 const void *data, int data_len)
2092{
2093 int ret;
2094
2095 cds_ssr_protect(__func__);
2096 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2097 cds_ssr_unprotect(__func__);
2098
2099 return ret;
2100}
2101
2102/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002103 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2104 * @adapter: Pointer to adapter struct
2105 *
2106 * This function handle cleanup of what was done in DO_ACS, including free
2107 * memory.
2108 *
2109 * Return: void
2110 */
2111
2112void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2113{
2114 if (adapter == NULL)
2115 return;
2116 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2117 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2118 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2119 }
2120}
2121
2122/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002123 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2124 * @work: Linux workqueue struct pointer for ACS work
2125 *
2126 * This function starts the ACS procedure which was marked pending when an ACS
2127 * procedure was in progress for a concurrent SAP interface.
2128 *
2129 * Return: None
2130 */
2131
2132static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2133{
2134 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2135 acs_pending_work.work);
2136 wlan_hdd_cfg80211_start_acs(adapter);
2137}
2138
2139/**
2140 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2141 * @adapter: Pointer to SAP adapter struct
2142 * @pri_channel: SAP ACS procedure selected Primary channel
2143 * @sec_channel: SAP ACS procedure selected secondary channel
2144 *
2145 * This is a callback function from SAP module on ACS procedure is completed.
2146 * This function send the ACS selected channel information to hostapd
2147 *
2148 * Return: None
2149 */
2150
2151void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2152{
2153 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2154 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2155 struct sk_buff *vendor_event;
2156 int ret_val;
2157 hdd_adapter_t *con_sap_adapter;
2158 uint16_t ch_width;
2159
2160 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002161 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2163 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2164 GFP_KERNEL);
2165
2166 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002167 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002168 return;
2169 }
2170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 ret_val = nla_put_u8(vendor_event,
2172 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2173 sap_cfg->acs_cfg.pri_ch);
2174 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002175 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 kfree_skb(vendor_event);
2177 return;
2178 }
2179
2180 ret_val = nla_put_u8(vendor_event,
2181 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2182 sap_cfg->acs_cfg.ht_sec_ch);
2183 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002184 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 kfree_skb(vendor_event);
2186 return;
2187 }
2188
2189 ret_val = nla_put_u8(vendor_event,
2190 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2191 sap_cfg->acs_cfg.vht_seg0_center_ch);
2192 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002193 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 kfree_skb(vendor_event);
2195 return;
2196 }
2197
2198 ret_val = nla_put_u8(vendor_event,
2199 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2200 sap_cfg->acs_cfg.vht_seg1_center_ch);
2201 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002202 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002203 kfree_skb(vendor_event);
2204 return;
2205 }
2206
2207 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2208 ch_width = 80;
2209 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2210 ch_width = 40;
2211 else
2212 ch_width = 20;
2213
2214 ret_val = nla_put_u16(vendor_event,
2215 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2216 ch_width);
2217 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002218 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 kfree_skb(vendor_event);
2220 return;
2221 }
2222 if (sap_cfg->acs_cfg.pri_ch > 14)
2223 ret_val = nla_put_u8(vendor_event,
2224 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2225 QCA_ACS_MODE_IEEE80211A);
2226 else
2227 ret_val = nla_put_u8(vendor_event,
2228 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2229 QCA_ACS_MODE_IEEE80211G);
2230
2231 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002232 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002233 kfree_skb(vendor_event);
2234 return;
2235 }
2236
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002237 hdd_debug("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002238 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2239 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2240 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2241
2242 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2243 /* ***Note*** As already mentioned Completion variable usage is not
2244 * allowed here since ACS scan operation may take max 2.2 sec.
2245 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2246 * operation.
2247 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2248 * when Primary AP ACS is complete and secondary AP ACS is started here
2249 * immediately, Primary AP start_bss may come inbetween ACS operation
2250 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2251 * delay. This path and below constraint will be removed on sessionizing
2252 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2253 * As per design constraint user space control application must take
2254 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2255 * this code path. Sec AP hostapd should be started after Primary AP
2256 * start beaconing which can be confirmed by getchannel iwpriv command
2257 */
2258
2259 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2260 if (con_sap_adapter &&
2261 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2263 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002264 /* Lets give 500ms for OBSS + START_BSS to complete */
2265 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2266 msecs_to_jiffies(500));
2267 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2268 }
2269
2270 return;
2271}
2272
2273static int
2274__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2275 struct wireless_dev *wdev,
2276 const void *data,
2277 int data_len)
2278{
2279 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2280 struct sk_buff *skb = NULL;
2281 uint32_t fset = 0;
2282 int ret;
2283
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002284 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302285
Anurag Chouhan6d760662016-02-20 16:05:43 +05302286 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002287 hdd_err("Command not allowed in FTM mode");
2288 return -EPERM;
2289 }
2290
2291 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302292 if (ret)
2293 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002294
2295 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002296 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297 fset |= WIFI_FEATURE_INFRA;
2298 }
2299 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002300 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 fset |= WIFI_FEATURE_INFRA_5G;
2302 }
2303#ifdef WLAN_FEATURE_P2P
2304 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2305 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002306 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002307 fset |= WIFI_FEATURE_P2P;
2308 }
2309#endif
2310 fset |= WIFI_FEATURE_SOFT_AP;
2311
2312 /* HOTSPOT is a supplicant feature, enable it by default */
2313 fset |= WIFI_FEATURE_HOTSPOT;
2314
2315#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302316 if (pHddCtx->config->extscan_enabled &&
2317 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002318 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002319 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2320 }
2321#endif
2322 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002323 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324 fset |= WIFI_FEATURE_NAN;
2325 }
2326 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002327 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002328 fset |= WIFI_FEATURE_D2D_RTT;
2329 fset |= WIFI_FEATURE_D2AP_RTT;
2330 }
2331#ifdef FEATURE_WLAN_SCAN_PNO
2332 if (pHddCtx->config->configPNOScanSupport &&
2333 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002334 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 fset |= WIFI_FEATURE_PNO;
2336 }
2337#endif
2338 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2339#ifdef FEATURE_WLAN_TDLS
2340 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2341 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002342 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 fset |= WIFI_FEATURE_TDLS;
2344 }
2345 if (sme_is_feature_supported_by_fw(TDLS) &&
2346 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2347 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002348 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2350 }
2351#endif
2352#ifdef WLAN_AP_STA_CONCURRENCY
2353 fset |= WIFI_FEATURE_AP_STA;
2354#endif
2355 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002356 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357
2358 if (hdd_link_layer_stats_supported())
2359 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2360
2361 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2362 NLMSG_HDRLEN);
2363 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002364 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365 return -EINVAL;
2366 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002367 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002368 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002369 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370 goto nla_put_failure;
2371 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302372 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302373 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374nla_put_failure:
2375 kfree_skb(skb);
2376 return -EINVAL;
2377}
2378
2379/**
2380 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2381 * @wiphy: pointer to wireless wiphy structure.
2382 * @wdev: pointer to wireless_dev structure.
2383 * @data: Pointer to the data to be passed via vendor interface
2384 * @data_len:Length of the data to be passed
2385 *
2386 * Return: Return the Success or Failure code.
2387 */
2388static int
2389wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2390 struct wireless_dev *wdev,
2391 const void *data, int data_len)
2392{
2393 int ret = 0;
2394
2395 cds_ssr_protect(__func__);
2396 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2397 data, data_len);
2398 cds_ssr_unprotect(__func__);
2399
2400 return ret;
2401}
2402
2403/**
2404 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2405 * @wiphy: pointer to wireless wiphy structure.
2406 * @wdev: pointer to wireless_dev structure.
2407 * @data: Pointer to the data to be passed via vendor interface
2408 * @data_len:Length of the data to be passed
2409 *
2410 * Set the MAC address that is to be used for scanning.
2411 *
2412 * Return: Return the Success or Failure code.
2413 */
2414static int
2415__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2416 struct wireless_dev *wdev,
2417 const void *data,
2418 int data_len)
2419{
2420 tpSirScanMacOui pReqMsg = NULL;
2421 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2422 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302423 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002424 int ret;
2425
Jeff Johnson1f61b612016-02-12 16:28:33 -08002426 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002427
Anurag Chouhan6d760662016-02-20 16:05:43 +05302428 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 hdd_err("Command not allowed in FTM mode");
2430 return -EPERM;
2431 }
2432
2433 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302434 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436
2437 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002438 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 return -ENOTSUPP;
2440 }
2441
2442 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2443 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002444 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 return -EINVAL;
2446 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302447 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002448 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002449 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 return -ENOMEM;
2451 }
2452 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002453 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 goto fail;
2455 }
2456 nla_memcpy(&pReqMsg->oui[0],
2457 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2458 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002459 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 pReqMsg->oui[1], pReqMsg->oui[2]);
2461 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302462 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002463 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 goto fail;
2465 }
2466 return 0;
2467fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302468 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 return -EINVAL;
2470}
2471
2472/**
2473 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2474 * @wiphy: pointer to wireless wiphy structure.
2475 * @wdev: pointer to wireless_dev structure.
2476 * @data: Pointer to the data to be passed via vendor interface
2477 * @data_len:Length of the data to be passed
2478 *
2479 * Set the MAC address that is to be used for scanning. This is an
2480 * SSR-protecting wrapper function.
2481 *
2482 * Return: Return the Success or Failure code.
2483 */
2484static int
2485wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2486 struct wireless_dev *wdev,
2487 const void *data,
2488 int data_len)
2489{
2490 int ret;
2491
2492 cds_ssr_protect(__func__);
2493 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2494 data, data_len);
2495 cds_ssr_unprotect(__func__);
2496
2497 return ret;
2498}
2499
2500/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302501 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2502 * @wiphy: pointer phy adapter
2503 * @wdev: pointer to wireless device structure
2504 * @data: pointer to data buffer
2505 * @data_len: length of data
2506 *
2507 * This routine will give concurrency matrix
2508 *
2509 * Return: int status code
2510 */
2511static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2512 struct wireless_dev *wdev,
2513 const void *data,
2514 int data_len)
2515{
2516 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2517 uint8_t i, feature_sets, max_feature_sets;
2518 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2519 struct sk_buff *reply_skb;
2520 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2521 int ret;
2522
2523 ENTER_DEV(wdev->netdev);
2524
2525 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2526 hdd_err("Command not allowed in FTM mode");
2527 return -EPERM;
2528 }
2529
2530 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302531 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302532 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302533
2534 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2535 data, data_len, NULL)) {
2536 hdd_err("Invalid ATTR");
2537 return -EINVAL;
2538 }
2539
2540 /* Parse and fetch max feature set */
2541 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2542 hdd_err("Attr max feature set size failed");
2543 return -EINVAL;
2544 }
2545 max_feature_sets = nla_get_u32(tb[
2546 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002547 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302548
2549 /* Fill feature combination matrix */
2550 feature_sets = 0;
2551 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002552 WIFI_FEATURE_P2P;
2553 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2554 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302555 /* Add more feature combinations here */
2556
2557 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002558 hdd_debug("Number of feature sets: %d", feature_sets);
2559 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302560 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002561 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302562
2563 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2564 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2565 if (!reply_skb) {
2566 hdd_err("Feature set matrix: buffer alloc fail");
2567 return -ENOMEM;
2568 }
2569
2570 if (nla_put_u32(reply_skb,
2571 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2572 feature_sets) ||
2573 nla_put(reply_skb,
2574 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2575 sizeof(u32) * feature_sets,
2576 feature_set_matrix)) {
2577 hdd_err("nla put fail");
2578 kfree_skb(reply_skb);
2579 return -EINVAL;
2580 }
2581 return cfg80211_vendor_cmd_reply(reply_skb);
2582}
2583
2584/**
2585 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2586 * @wiphy: pointer to wireless wiphy structure.
2587 * @wdev: pointer to wireless_dev structure.
2588 * @data: Pointer to the data to be passed via vendor interface
2589 * @data_len:Length of the data to be passed
2590 *
2591 * Retrieves the concurrency feature set matrix
2592 *
2593 * Return: 0 on success, negative errno on failure
2594 */
2595static int
2596wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2597 struct wireless_dev *wdev,
2598 const void *data,
2599 int data_len)
2600{
2601 int ret;
2602
2603 cds_ssr_protect(__func__);
2604 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2605 data, data_len);
2606 cds_ssr_unprotect(__func__);
2607
2608 return ret;
2609}
2610
2611/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2613 * @feature_flags: pointer to the byte array of features.
2614 * @feature: Feature to be turned ON in the byte array.
2615 *
2616 * Return: None
2617 *
2618 * This is called to turn ON or SET the feature flag for the requested feature.
2619 **/
2620#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002621static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2622 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002623{
2624 uint32_t index;
2625 uint8_t bit_mask;
2626
2627 index = feature / NUM_BITS_IN_BYTE;
2628 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2629 feature_flags[index] |= bit_mask;
2630}
2631
2632/**
2633 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2634 * @wiphy: pointer to wireless wiphy structure.
2635 * @wdev: pointer to wireless_dev structure.
2636 * @data: Pointer to the data to be passed via vendor interface
2637 * @data_len:Length of the data to be passed
2638 *
2639 * This is called when wlan driver needs to send supported feature set to
2640 * supplicant upon a request/query from the supplicant.
2641 *
2642 * Return: Return the Success or Failure code.
2643 **/
2644#define MAX_CONCURRENT_CHAN_ON_24G 2
2645#define MAX_CONCURRENT_CHAN_ON_5G 2
2646static int
2647__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2648 struct wireless_dev *wdev,
2649 const void *data, int data_len)
2650{
2651 struct sk_buff *skb = NULL;
2652 uint32_t dbs_capability = 0;
2653 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302654 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002655 int ret_val;
2656
2657 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2658 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2659
Jeff Johnson1f61b612016-02-12 16:28:33 -08002660 ENTER_DEV(wdev->netdev);
2661
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002662 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2663 if (ret_val)
2664 return ret_val;
2665
Anurag Chouhan6d760662016-02-20 16:05:43 +05302666 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002667 hdd_err("Command not allowed in FTM mode");
2668 return -EPERM;
2669 }
2670
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002671 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002672 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 wlan_hdd_cfg80211_set_feature(feature_flags,
2674 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2675 }
2676
2677 wlan_hdd_cfg80211_set_feature(feature_flags,
2678 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002679 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 wlan_hdd_cfg80211_set_feature(feature_flags,
2681 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002682
2683 if (wma_is_p2p_lo_capable())
2684 wlan_hdd_cfg80211_set_feature(feature_flags,
2685 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2686
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2688 NLMSG_HDRLEN);
2689
2690 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002691 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002692 return -ENOMEM;
2693 }
2694
2695 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2696 sizeof(feature_flags), feature_flags))
2697 goto nla_put_failure;
2698
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002699 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2700 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302701 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702 if (one_by_one_dbs)
2703 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2704
2705 if (two_by_two_dbs)
2706 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2707
2708 if (!one_by_one_dbs && !two_by_two_dbs)
2709 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2710 } else {
2711 hdd_err("wma_get_dbs_hw_mode failed");
2712 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2713 }
2714
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002715 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716
2717 if (nla_put_u32(skb,
2718 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2719 MAX_CONCURRENT_CHAN_ON_24G))
2720 goto nla_put_failure;
2721
2722 if (nla_put_u32(skb,
2723 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2724 MAX_CONCURRENT_CHAN_ON_5G))
2725 goto nla_put_failure;
2726
2727 return cfg80211_vendor_cmd_reply(skb);
2728
2729nla_put_failure:
2730 kfree_skb(skb);
2731 return -EINVAL;
2732}
2733
2734/**
2735 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2736 * @wiphy: pointer to wireless wiphy structure.
2737 * @wdev: pointer to wireless_dev structure.
2738 * @data: Pointer to the data to be passed via vendor interface
2739 * @data_len:Length of the data to be passed
2740 *
2741 * This is called when wlan driver needs to send supported feature set to
2742 * supplicant upon a request/query from the supplicant.
2743 *
2744 * Return: Return the Success or Failure code.
2745 */
2746static int
2747wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2748 struct wireless_dev *wdev,
2749 const void *data, int data_len)
2750{
2751 int ret;
2752
2753 cds_ssr_protect(__func__);
2754 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2755 data, data_len);
2756 cds_ssr_unprotect(__func__);
2757
2758 return ret;
2759}
2760
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302761#define PARAM_NUM_NW \
2762 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2763#define PARAM_SET_BSSID \
2764 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2765#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2766#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767
2768/**
2769 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2770 * @wiphy: The wiphy structure
2771 * @wdev: The wireless device
2772 * @data: Data passed by framework
2773 * @data_len: Parameters to be configured passed as data
2774 *
2775 * The roaming related parameters are configured by the framework
2776 * using this interface.
2777 *
2778 * Return: Return either success or failure code.
2779 */
2780static int
2781__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2782 struct wireless_dev *wdev, const void *data, int data_len)
2783{
2784 struct net_device *dev = wdev->netdev;
2785 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2786 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2787 uint8_t session_id;
2788 struct roam_ext_params roam_params;
2789 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302790 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2792 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2793 int rem, i;
2794 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002795 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796 int ret;
2797
Jeff Johnson1f61b612016-02-12 16:28:33 -08002798 ENTER_DEV(dev);
2799
Anurag Chouhan6d760662016-02-20 16:05:43 +05302800 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801 hdd_err("Command not allowed in FTM mode");
2802 return -EPERM;
2803 }
2804
2805 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302806 if (ret)
2807 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808
2809 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2810 data, data_len,
2811 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002812 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 return -EINVAL;
2814 }
2815 /* Parse and fetch Command Type*/
2816 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002817 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002818 goto fail;
2819 }
2820 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302821 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002822 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2823 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002824 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002825 goto fail;
2826 }
2827 req_id = nla_get_u32(
2828 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002829 hdd_debug("Req Id (%d)", req_id);
2830 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002831 switch (cmd_type) {
2832 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2833 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302834 if (tb[PARAM_NUM_NW]) {
2835 count = nla_get_u32(
2836 tb[PARAM_NUM_NW]);
2837 } else {
2838 hdd_err("Number of networks is not provided");
2839 goto fail;
2840 }
2841
2842 if (count &&
2843 tb[PRAM_SSID_LIST]) {
2844 nla_for_each_nested(curr_attr,
2845 tb[PRAM_SSID_LIST], rem) {
2846 if (nla_parse(tb2,
2847 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2848 nla_data(curr_attr), nla_len(curr_attr),
2849 NULL)) {
2850 hdd_err("nla_parse failed");
2851 goto fail;
2852 }
2853 /* Parse and Fetch allowed SSID list*/
2854 if (!tb2[PARAM_LIST_SSID]) {
2855 hdd_err("attr allowed ssid failed");
2856 goto fail;
2857 }
2858 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2859 /*
2860 * Upper Layers include a null termination
2861 * character. Check for the actual permissible
2862 * length of SSID and also ensure not to copy
2863 * the NULL termination character to the driver
2864 * buffer.
2865 */
2866 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2867 ((buf_len - 1) <=
2868 SIR_MAC_MAX_SSID_LENGTH)) {
2869 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002870 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302871 tb2[PARAM_LIST_SSID], buf_len - 1);
2872 roam_params.ssid_allowed_list[i].length
2873 = buf_len - 1;
2874 hdd_debug("SSID[%d]: %.*s,length = %d",
2875 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002876 roam_params.ssid_allowed_list[i].length,
2877 roam_params.ssid_allowed_list[i].ssId,
2878 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302879 i++;
2880 } else {
2881 hdd_err("Invalid buffer length");
2882 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883 }
2884 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302885 if (i != count) {
2886 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2887 i, count);
2888 goto fail;
2889 }
2890
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002892 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893 roam_params.num_ssid_allowed_list);
2894 sme_update_roam_params(pHddCtx->hHal, session_id,
2895 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2896 break;
2897 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2898 /* Parse and fetch 5G Boost Threshold */
2899 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002900 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002901 goto fail;
2902 }
2903 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2904 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002905 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002906 roam_params.raise_rssi_thresh_5g);
2907 /* Parse and fetch 5G Penalty Threshold */
2908 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002909 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910 goto fail;
2911 }
2912 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2913 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002914 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 roam_params.drop_rssi_thresh_5g);
2916 /* Parse and fetch 5G Boost Factor */
2917 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002918 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 goto fail;
2920 }
2921 roam_params.raise_factor_5g = nla_get_u32(
2922 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002923 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002924 roam_params.raise_factor_5g);
2925 /* Parse and fetch 5G Penalty factor */
2926 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002927 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928 goto fail;
2929 }
2930 roam_params.drop_factor_5g = nla_get_u32(
2931 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002932 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002933 roam_params.drop_factor_5g);
2934 /* Parse and fetch 5G Max Boost */
2935 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002936 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002937 goto fail;
2938 }
2939 roam_params.max_raise_rssi_5g = nla_get_u32(
2940 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002941 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 roam_params.max_raise_rssi_5g);
2943 /* Parse and fetch Rssi Diff */
2944 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002945 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002946 goto fail;
2947 }
2948 roam_params.rssi_diff = nla_get_s32(
2949 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002950 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002951 roam_params.rssi_diff);
2952 /* Parse and fetch Alert Rssi Threshold */
2953 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002954 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002955 goto fail;
2956 }
2957 roam_params.alert_rssi_threshold = nla_get_u32(
2958 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002959 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 roam_params.alert_rssi_threshold);
2961 sme_update_roam_params(pHddCtx->hHal, session_id,
2962 roam_params,
2963 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2964 break;
2965 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2966 /* Parse and fetch Activate Good Rssi Roam */
2967 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002968 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002969 goto fail;
2970 }
2971 roam_params.good_rssi_roam = nla_get_s32(
2972 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002973 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002974 roam_params.good_rssi_roam);
2975 sme_update_roam_params(pHddCtx->hHal, session_id,
2976 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2977 break;
2978 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2979 /* Parse and fetch number of preferred BSSID */
2980 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002981 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982 goto fail;
2983 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002984 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002986 if (count > MAX_BSSID_FAVORED) {
2987 hdd_err("Preferred BSSID count %u exceeds max %u",
2988 count, MAX_BSSID_FAVORED);
2989 goto fail;
2990 }
2991 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002992 i = 0;
2993 nla_for_each_nested(curr_attr,
2994 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2995 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002996
2997 if (i == count) {
2998 hdd_warn("Ignoring excess Preferred BSSID");
2999 break;
3000 }
3001
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 if (nla_parse(tb2,
3003 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3004 nla_data(curr_attr), nla_len(curr_attr),
3005 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003006 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 goto fail;
3008 }
3009 /* Parse and fetch MAC address */
3010 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003011 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012 goto fail;
3013 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003014 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003015 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303016 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003017 hdd_debug(MAC_ADDRESS_STR,
3018 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003019 /* Parse and fetch preference factor*/
3020 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003021 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003022 goto fail;
3023 }
3024 roam_params.bssid_favored_factor[i] = nla_get_u32(
3025 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003026 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 roam_params.bssid_favored_factor[i]);
3028 i++;
3029 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003030 if (i < count)
3031 hdd_warn("Num Preferred BSSID %u less than expected %u",
3032 i, count);
3033 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 sme_update_roam_params(pHddCtx->hHal, session_id,
3035 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3036 break;
3037 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3038 /* Parse and fetch number of blacklist BSSID */
3039 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003040 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003041 goto fail;
3042 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003043 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003044 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003045 if (count > MAX_BSSID_AVOID_LIST) {
3046 hdd_err("Blacklist BSSID count %u exceeds max %u",
3047 count, MAX_BSSID_AVOID_LIST);
3048 goto fail;
3049 }
3050 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303052
3053 if (count &&
3054 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3055 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3057 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003058
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303059 if (i == count) {
3060 hdd_warn("Ignoring excess Blacklist BSSID");
3061 break;
3062 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003063
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303064 if (nla_parse(tb2,
3065 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3066 nla_data(curr_attr), nla_len(curr_attr),
3067 NULL)) {
3068 hdd_err("nla_parse failed");
3069 goto fail;
3070 }
3071 /* Parse and fetch MAC address */
3072 if (!tb2[PARAM_SET_BSSID]) {
3073 hdd_err("attr blacklist addr failed");
3074 goto fail;
3075 }
3076 nla_memcpy(
3077 roam_params.bssid_avoid_list[i].bytes,
3078 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3079 hdd_debug(MAC_ADDRESS_STR,
3080 MAC_ADDR_ARRAY(
3081 roam_params.bssid_avoid_list[i].bytes));
3082 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003084 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003085 if (i < count)
3086 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3087 i, count);
3088 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003089 sme_update_roam_params(pHddCtx->hHal, session_id,
3090 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3091 break;
3092 }
3093 return 0;
3094fail:
3095 return -EINVAL;
3096}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303097#undef PARAM_NUM_NW
3098#undef PARAM_SET_BSSID
3099#undef PRAM_SSID_LIST
3100#undef PARAM_LIST_SSID
3101
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003102
3103/**
3104 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3105 * @wiphy: pointer to wireless wiphy structure.
3106 * @wdev: pointer to wireless_dev structure.
3107 * @data: Pointer to the data to be passed via vendor interface
3108 * @data_len:Length of the data to be passed
3109 *
3110 * Return: Return the Success or Failure code.
3111 */
3112static int
3113wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3114 struct wireless_dev *wdev,
3115 const void *data,
3116 int data_len)
3117{
3118 int ret;
3119
3120 cds_ssr_protect(__func__);
3121 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3122 data, data_len);
3123 cds_ssr_unprotect(__func__);
3124
3125 return ret;
3126}
3127
3128static const struct nla_policy
3129wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3130 +1] = {
3131 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3132};
3133
3134/**
3135 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3136 * @hdd_ctx: HDD context
3137 * @device_mode: device mode
3138 * Return: bool
3139 */
3140static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003141 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003142{
3143 hdd_adapter_t *adapter;
3144 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3145 hdd_ap_ctx_t *ap_ctx;
3146 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303147 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303149 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003150 &adapter_node);
3151
3152 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303153 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 adapter = adapter_node->pAdapter;
3155
3156 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003157 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158 ap_ctx =
3159 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3160
3161 /*
3162 * if there is SAP already running on DFS channel,
3163 * do not disable scan on dfs channels. Note that
3164 * with SAP on DFS, there cannot be conurrency on
3165 * single radio. But then we can have multiple
3166 * radios !!
3167 */
3168 if (CHANNEL_STATE_DFS ==
3169 cds_get_channel_state(
3170 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003171 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 return true;
3173 }
3174 }
3175
3176 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003177 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 sta_ctx =
3179 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3180
3181 /*
3182 * if STA is already connected on DFS channel,
3183 * do not disable scan on dfs channels
3184 */
3185 if (hdd_conn_is_connected(sta_ctx) &&
3186 (CHANNEL_STATE_DFS ==
3187 cds_get_channel_state(
3188 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003189 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 return true;
3191 }
3192 }
3193
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303194 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195 adapter_node,
3196 &next);
3197 adapter_node = next;
3198 }
3199
3200 return false;
3201}
3202
3203/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003204 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3205 * @hdd_ctx: HDD context within host driver
3206 * @adapter: Adapter pointer
3207 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3208 *
3209 * Loops through devices to see who is operating on DFS channels
3210 * and then disables/enables DFS channels by calling SME API.
3211 * Fails the disable request if any device is active on a DFS channel.
3212 *
3213 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003215
3216int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3217 hdd_adapter_t *adapter,
3218 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003219{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303221 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003223
3224 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3225 if (no_dfs_flag) {
3226 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003227 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228
3229 if (true == status)
3230 return -EOPNOTSUPP;
3231
3232 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003233 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234
3235 if (true == status)
3236 return -EOPNOTSUPP;
3237 }
3238
3239 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3240
3241 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3242
3243 /*
3244 * call the SME API to tunnel down the new channel list
3245 * to the firmware
3246 */
3247 status = sme_handle_dfs_chan_scan(
3248 h_hal, hdd_ctx->config->enableDFSChnlScan);
3249
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303250 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003251 ret_val = 0;
3252
3253 /*
3254 * Clear the SME scan cache also. Note that the
3255 * clearing of scan results is independent of session;
3256 * so no need to iterate over
3257 * all sessions
3258 */
3259 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303260 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261 ret_val = -EPERM;
3262 }
3263
3264 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003265 hdd_debug(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003266 ret_val = 0;
3267 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003268 return ret_val;
3269}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003271/**
3272 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3273 * @wiphy: corestack handler
3274 * @wdev: wireless device
3275 * @data: data
3276 * @data_len: data length
3277 * Return: success(0) or reason code for failure
3278 */
3279static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3280 struct wireless_dev *wdev,
3281 const void *data,
3282 int data_len)
3283{
3284 struct net_device *dev = wdev->netdev;
3285 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3286 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3287 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3288 int ret_val;
3289 uint32_t no_dfs_flag = 0;
3290
Jeff Johnson1f61b612016-02-12 16:28:33 -08003291 ENTER_DEV(dev);
3292
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003293 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303294 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003295 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003296
3297 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3298 data, data_len,
3299 wlan_hdd_set_no_dfs_flag_config_policy)) {
3300 hdd_err("invalid attr");
3301 return -EINVAL;
3302 }
3303
3304 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3305 hdd_err("attr dfs flag failed");
3306 return -EINVAL;
3307 }
3308
3309 no_dfs_flag = nla_get_u32(
3310 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3311
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003312 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003313
3314 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003315 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003316 return -EINVAL;
3317 }
3318
3319 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3320 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321 return ret_val;
3322}
3323
3324/**
3325 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3326 *
3327 * @wiphy: wiphy device pointer
3328 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003329 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003330 * @data_len: Buffer length
3331 *
3332 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3333 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3334 *
3335 * Return: EOK or other error codes.
3336 */
3337
3338static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3339 struct wireless_dev *wdev,
3340 const void *data,
3341 int data_len)
3342{
3343 int ret;
3344
3345 cds_ssr_protect(__func__);
3346 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3347 data, data_len);
3348 cds_ssr_unprotect(__func__);
3349
3350 return ret;
3351}
3352
Manikandan Mohan80dea792016-04-28 16:36:48 -07003353static const struct nla_policy
3354wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3355 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3356};
3357
3358/**
3359 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3360 * @wiphy: wiphy device pointer
3361 * @wdev: wireless device pointer
3362 * @data: Vendor command data buffer
3363 * @data_len: Buffer length
3364 *
3365 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3366 * setup WISA Mode features.
3367 *
3368 * Return: Success(0) or reason code for failure
3369 */
3370static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3371 struct wireless_dev *wdev, const void *data, int data_len)
3372{
3373 struct net_device *dev = wdev->netdev;
3374 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3375 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3376 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3377 struct sir_wisa_params wisa;
3378 int ret_val;
3379 QDF_STATUS status;
3380 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003381 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3382 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003383
3384 ENTER_DEV(dev);
3385 ret_val = wlan_hdd_validate_context(hdd_ctx);
3386 if (ret_val)
3387 goto err;
3388
3389 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3390 hdd_err("Command not allowed in FTM mode");
3391 return -EPERM;
3392 }
3393
3394 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3395 wlan_hdd_wisa_cmd_policy)) {
3396 hdd_err("Invalid WISA cmd attributes");
3397 ret_val = -EINVAL;
3398 goto err;
3399 }
3400 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3401 hdd_err("Invalid WISA mode");
3402 ret_val = -EINVAL;
3403 goto err;
3404 }
3405
3406 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003407 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003408 wisa.mode = wisa_mode;
3409 wisa.vdev_id = adapter->sessionId;
3410 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003411 if (!QDF_IS_STATUS_SUCCESS(status)) {
3412 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003413 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003414 }
3415 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003416 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003417 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3418 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003419 adapter->sessionId),
3420 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003421err:
3422 EXIT();
3423 return ret_val;
3424}
3425
3426/**
3427 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3428 * @wiphy: corestack handler
3429 * @wdev: wireless device
3430 * @data: data
3431 * @data_len: data length
3432 *
3433 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3434 * setup WISA mode features.
3435 *
3436 * Return: Success(0) or reason code for failure
3437 */
3438static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3439 struct wireless_dev *wdev,
3440 const void *data,
3441 int data_len)
3442{
3443 int ret;
3444
3445 cds_ssr_protect(__func__);
3446 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3447 cds_ssr_unprotect(__func__);
3448
3449 return ret;
3450}
3451
Anurag Chouhan96919482016-07-13 16:36:57 +05303452/*
3453 * define short names for the global vendor params
3454 * used by __wlan_hdd_cfg80211_get_station_cmd()
3455 */
3456#define STATION_INVALID \
3457 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3458#define STATION_INFO \
3459 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3460#define STATION_ASSOC_FAIL_REASON \
3461 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3462#define STATION_MAX \
3463 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3464
3465static const struct nla_policy
3466hdd_get_station_policy[STATION_MAX + 1] = {
3467 [STATION_INFO] = {.type = NLA_FLAG},
3468 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3469};
3470
3471/**
3472 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3473 * @hdd_ctx: HDD context within host driver
3474 * @wdev: wireless device
3475 *
3476 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3477 * Validate cmd attributes and send the station info to upper layers.
3478 *
3479 * Return: Success(0) or reason code for failure
3480 */
3481static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3482 hdd_adapter_t *adapter)
3483{
3484 struct sk_buff *skb = NULL;
3485 uint32_t nl_buf_len;
3486 hdd_station_ctx_t *hdd_sta_ctx;
3487
3488 nl_buf_len = NLMSG_HDRLEN;
3489 nl_buf_len += sizeof(uint32_t);
3490 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3491
3492 if (!skb) {
3493 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3494 return -ENOMEM;
3495 }
3496
3497 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3498
3499 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3500 hdd_sta_ctx->conn_info.assoc_status_code)) {
3501 hdd_err("put fail");
3502 goto fail;
3503 }
3504 return cfg80211_vendor_cmd_reply(skb);
3505fail:
3506 if (skb)
3507 kfree_skb(skb);
3508 return -EINVAL;
3509}
3510
3511/**
3512 * hdd_map_auth_type() - transform auth type specific to
3513 * vendor command
3514 * @auth_type: csr auth type
3515 *
3516 * Return: Success(0) or reason code for failure
3517 */
3518static int hdd_convert_auth_type(uint32_t auth_type)
3519{
3520 uint32_t ret_val;
3521
3522 switch (auth_type) {
3523 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3524 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3525 break;
3526 case eCSR_AUTH_TYPE_SHARED_KEY:
3527 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3528 break;
3529 case eCSR_AUTH_TYPE_WPA:
3530 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3531 break;
3532 case eCSR_AUTH_TYPE_WPA_PSK:
3533 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3534 break;
3535 case eCSR_AUTH_TYPE_AUTOSWITCH:
3536 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3537 break;
3538 case eCSR_AUTH_TYPE_WPA_NONE:
3539 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3540 break;
3541 case eCSR_AUTH_TYPE_RSN:
3542 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3543 break;
3544 case eCSR_AUTH_TYPE_RSN_PSK:
3545 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3546 break;
3547 case eCSR_AUTH_TYPE_FT_RSN:
3548 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3549 break;
3550 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3551 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3552 break;
3553 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3554 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3555 break;
3556 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3557 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3558 break;
3559 case eCSR_AUTH_TYPE_CCKM_WPA:
3560 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3561 break;
3562 case eCSR_AUTH_TYPE_CCKM_RSN:
3563 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3564 break;
3565 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3566 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3567 break;
3568 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3569 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3570 break;
3571 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3572 case eCSR_AUTH_TYPE_FAILED:
3573 case eCSR_AUTH_TYPE_NONE:
3574 default:
3575 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3576 break;
3577 }
3578 return ret_val;
3579}
3580
3581/**
3582 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3583 * vendor command
3584 * @dot11mode: dot11mode
3585 *
3586 * Return: Success(0) or reason code for failure
3587 */
3588static int hdd_convert_dot11mode(uint32_t dot11mode)
3589{
3590 uint32_t ret_val;
3591
3592 switch (dot11mode) {
3593 case eCSR_CFG_DOT11_MODE_11A:
3594 ret_val = QCA_WLAN_802_11_MODE_11A;
3595 break;
3596 case eCSR_CFG_DOT11_MODE_11B:
3597 ret_val = QCA_WLAN_802_11_MODE_11B;
3598 break;
3599 case eCSR_CFG_DOT11_MODE_11G:
3600 ret_val = QCA_WLAN_802_11_MODE_11G;
3601 break;
3602 case eCSR_CFG_DOT11_MODE_11N:
3603 ret_val = QCA_WLAN_802_11_MODE_11N;
3604 break;
3605 case eCSR_CFG_DOT11_MODE_11AC:
3606 ret_val = QCA_WLAN_802_11_MODE_11AC;
3607 break;
3608 case eCSR_CFG_DOT11_MODE_AUTO:
3609 case eCSR_CFG_DOT11_MODE_ABG:
3610 default:
3611 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3612 }
3613 return ret_val;
3614}
3615
3616/**
3617 * hdd_add_tx_bitrate() - add tx bitrate attribute
3618 * @skb: pointer to sk buff
3619 * @hdd_sta_ctx: pointer to hdd station context
3620 * @idx: attribute index
3621 *
3622 * Return: Success(0) or reason code for failure
3623 */
3624static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3625 hdd_station_ctx_t *hdd_sta_ctx,
3626 int idx)
3627{
3628 struct nlattr *nla_attr;
3629 uint32_t bitrate, bitrate_compat;
3630
3631 nla_attr = nla_nest_start(skb, idx);
3632 if (!nla_attr)
3633 goto fail;
3634 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3635 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3636
3637 /* report 16-bit bitrate only if we can */
3638 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3639 if (bitrate > 0 &&
3640 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3641 hdd_err("put fail");
3642 goto fail;
3643 }
3644 if (bitrate_compat > 0 &&
3645 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3646 hdd_err("put fail");
3647 goto fail;
3648 }
3649 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3650 hdd_sta_ctx->conn_info.txrate.nss)) {
3651 hdd_err("put fail");
3652 goto fail;
3653 }
3654 nla_nest_end(skb, nla_attr);
3655 return 0;
3656fail:
3657 return -EINVAL;
3658}
3659
3660/**
3661 * hdd_add_sta_info() - add station info attribute
3662 * @skb: pointer to sk buff
3663 * @hdd_sta_ctx: pointer to hdd station context
3664 * @idx: attribute index
3665 *
3666 * Return: Success(0) or reason code for failure
3667 */
3668static int32_t hdd_add_sta_info(struct sk_buff *skb,
3669 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3670{
3671 struct nlattr *nla_attr;
3672
3673 nla_attr = nla_nest_start(skb, idx);
3674 if (!nla_attr)
3675 goto fail;
3676 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3677 (hdd_sta_ctx->conn_info.signal + 100))) {
3678 hdd_err("put fail");
3679 goto fail;
3680 }
3681 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3682 goto fail;
3683 nla_nest_end(skb, nla_attr);
3684 return 0;
3685fail:
3686 return -EINVAL;
3687}
3688
3689/**
3690 * hdd_add_survey_info() - add survey info attribute
3691 * @skb: pointer to sk buff
3692 * @hdd_sta_ctx: pointer to hdd station context
3693 * @idx: attribute index
3694 *
3695 * Return: Success(0) or reason code for failure
3696 */
3697static int32_t hdd_add_survey_info(struct sk_buff *skb,
3698 hdd_station_ctx_t *hdd_sta_ctx,
3699 int idx)
3700{
3701 struct nlattr *nla_attr;
3702
3703 nla_attr = nla_nest_start(skb, idx);
3704 if (!nla_attr)
3705 goto fail;
3706 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3707 hdd_sta_ctx->conn_info.freq) ||
3708 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3709 (hdd_sta_ctx->conn_info.noise + 100))) {
3710 hdd_err("put fail");
3711 goto fail;
3712 }
3713 nla_nest_end(skb, nla_attr);
3714 return 0;
3715fail:
3716 return -EINVAL;
3717}
3718
3719/**
3720 * hdd_add_link_standard_info() - add link info attribute
3721 * @skb: pointer to sk buff
3722 * @hdd_sta_ctx: pointer to hdd station context
3723 * @idx: attribute index
3724 *
3725 * Return: Success(0) or reason code for failure
3726 */
3727static int32_t
3728hdd_add_link_standard_info(struct sk_buff *skb,
3729 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3730{
3731 struct nlattr *nla_attr;
3732
3733 nla_attr = nla_nest_start(skb, idx);
3734 if (!nla_attr)
3735 goto fail;
3736 if (nla_put(skb,
3737 NL80211_ATTR_SSID,
3738 hdd_sta_ctx->conn_info.SSID.SSID.length,
3739 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3740 hdd_err("put fail");
3741 goto fail;
3742 }
3743 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3744 goto fail;
3745 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3746 goto fail;
3747 nla_nest_end(skb, nla_attr);
3748 return 0;
3749fail:
3750 return -EINVAL;
3751}
3752
3753/**
3754 * hdd_add_ap_standard_info() - add ap info attribute
3755 * @skb: pointer to sk buff
3756 * @hdd_sta_ctx: pointer to hdd station context
3757 * @idx: attribute index
3758 *
3759 * Return: Success(0) or reason code for failure
3760 */
3761static int32_t
3762hdd_add_ap_standard_info(struct sk_buff *skb,
3763 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3764{
3765 struct nlattr *nla_attr;
3766
3767 nla_attr = nla_nest_start(skb, idx);
3768 if (!nla_attr)
3769 goto fail;
3770 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3771 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3772 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3773 &hdd_sta_ctx->conn_info.vht_caps)) {
3774 hdd_err("put fail");
3775 goto fail;
3776 }
3777 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3778 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3779 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3780 &hdd_sta_ctx->conn_info.ht_caps)) {
3781 hdd_err("put fail");
3782 goto fail;
3783 }
3784 nla_nest_end(skb, nla_attr);
3785 return 0;
3786fail:
3787 return -EINVAL;
3788}
3789
3790/**
3791 * hdd_get_station_info() - send BSS information to supplicant
3792 * @hdd_ctx: pointer to hdd context
3793 * @adapter: pointer to adapter
3794 *
3795 * Return: 0 if success else error status
3796 */
3797static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3798 hdd_adapter_t *adapter)
3799{
3800 struct sk_buff *skb = NULL;
3801 uint8_t *tmp_hs20 = NULL;
3802 uint32_t nl_buf_len;
3803 hdd_station_ctx_t *hdd_sta_ctx;
3804
3805 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3806
3807 nl_buf_len = NLMSG_HDRLEN;
3808 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3809 sizeof(hdd_sta_ctx->conn_info.freq) +
3810 sizeof(hdd_sta_ctx->conn_info.noise) +
3811 sizeof(hdd_sta_ctx->conn_info.signal) +
3812 (sizeof(uint32_t) * 2) +
3813 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3814 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3815 sizeof(hdd_sta_ctx->conn_info.authType) +
3816 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3817 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3818 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3819 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3820 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3821 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3822 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3823 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3824 1);
3825 }
3826 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3827 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3828 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3829 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3830
3831
3832 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3833 if (!skb) {
3834 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3835 return -ENOMEM;
3836 }
3837
3838 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3839 LINK_INFO_STANDARD_NL80211_ATTR)) {
3840 hdd_err("put fail");
3841 goto fail;
3842 }
3843 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3844 AP_INFO_STANDARD_NL80211_ATTR)) {
3845 hdd_err("put fail");
3846 goto fail;
3847 }
3848 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3849 hdd_sta_ctx->conn_info.roam_count) ||
3850 nla_put_u32(skb, INFO_AKM,
3851 hdd_convert_auth_type(
3852 hdd_sta_ctx->conn_info.authType)) ||
3853 nla_put_u32(skb, WLAN802_11_MODE,
3854 hdd_convert_dot11mode(
3855 hdd_sta_ctx->conn_info.dot11Mode))) {
3856 hdd_err("put fail");
3857 goto fail;
3858 }
3859 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3860 if (nla_put(skb, HT_OPERATION,
3861 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3862 &hdd_sta_ctx->conn_info.ht_operation)) {
3863 hdd_err("put fail");
3864 goto fail;
3865 }
3866 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3867 if (nla_put(skb, VHT_OPERATION,
3868 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3869 &hdd_sta_ctx->conn_info.vht_operation)) {
3870 hdd_err("put fail");
3871 goto fail;
3872 }
3873 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3874 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3875 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3876 tmp_hs20 + 1)) {
3877 hdd_err("put fail");
3878 goto fail;
3879 }
3880
3881 return cfg80211_vendor_cmd_reply(skb);
3882fail:
3883 if (skb)
3884 kfree_skb(skb);
3885 return -EINVAL;
3886}
3887
3888/**
3889 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3890 * @wiphy: corestack handler
3891 * @wdev: wireless device
3892 * @data: data
3893 * @data_len: data length
3894 *
3895 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3896 * Validate cmd attributes and send the station info to upper layers.
3897 *
3898 * Return: Success(0) or reason code for failure
3899 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303900static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303901__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3902 struct wireless_dev *wdev,
3903 const void *data,
3904 int data_len)
3905{
3906 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3907 struct net_device *dev = wdev->netdev;
3908 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3909 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3910 int32_t status;
3911
3912 ENTER_DEV(dev);
3913 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3914 hdd_err("Command not allowed in FTM mode");
3915 status = -EPERM;
3916 goto out;
3917 }
3918
3919 status = wlan_hdd_validate_context(hdd_ctx);
3920 if (0 != status)
3921 goto out;
3922
3923
3924 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3925 data, data_len, NULL);
3926 if (status) {
3927 hdd_err("Invalid ATTR");
3928 goto out;
3929 }
3930
3931 /* Parse and fetch Command Type*/
3932 if (tb[STATION_INFO]) {
3933 status = hdd_get_station_info(hdd_ctx, adapter);
3934 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3935 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3936 } else {
3937 hdd_err("get station info cmd type failed");
3938 status = -EINVAL;
3939 goto out;
3940 }
3941 EXIT();
3942out:
3943 return status;
3944}
3945
3946/**
3947 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3948 * @wiphy: corestack handler
3949 * @wdev: wireless device
3950 * @data: data
3951 * @data_len: data length
3952 *
3953 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3954 * Validate cmd attributes and send the station info to upper layers.
3955 *
3956 * Return: Success(0) or reason code for failure
3957 */
3958static int32_t
3959hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3960 struct wireless_dev *wdev,
3961 const void *data,
3962 int data_len)
3963{
3964 int ret;
3965
3966 cds_ssr_protect(__func__);
3967 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3968 cds_ssr_unprotect(__func__);
3969
3970 return ret;
3971}
3972
3973/*
3974 * undef short names defined for get station command
3975 * used by __wlan_hdd_cfg80211_get_station_cmd()
3976 */
3977#undef STATION_INVALID
3978#undef STATION_INFO
3979#undef STATION_ASSOC_FAIL_REASON
3980#undef STATION_MAX
3981
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003982#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3983/**
3984 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3985 * @wiphy: pointer to wireless wiphy structure.
3986 * @wdev: pointer to wireless_dev structure.
3987 * @data: Pointer to the Key data
3988 * @data_len:Length of the data passed
3989 *
3990 * This is called when wlan driver needs to save the keys received via
3991 * vendor specific command.
3992 *
3993 * Return: Return the Success or Failure code.
3994 */
3995static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3996 struct wireless_dev *wdev,
3997 const void *data, int data_len)
3998{
3999 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4000 struct net_device *dev = wdev->netdev;
4001 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4002 hdd_context_t *hdd_ctx_ptr;
4003 int status;
4004
Jeff Johnson1f61b612016-02-12 16:28:33 -08004005 ENTER_DEV(dev);
4006
Anurag Chouhan6d760662016-02-20 16:05:43 +05304007 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 hdd_err("Command not allowed in FTM mode");
4009 return -EPERM;
4010 }
4011
4012 if ((data == NULL) || (data_len == 0) ||
4013 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004014 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015 return -EINVAL;
4016 }
4017
4018 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4019 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004020 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 return -EINVAL;
4022 }
4023
4024 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304025 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004026 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4028 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004029 true,
4030 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304031 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4032 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4034 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4035 return 0;
4036}
4037
4038/**
4039 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4040 * @wiphy: pointer to wireless wiphy structure.
4041 * @wdev: pointer to wireless_dev structure.
4042 * @data: Pointer to the Key data
4043 * @data_len:Length of the data passed
4044 *
4045 * This is called when wlan driver needs to save the keys received via
4046 * vendor specific command.
4047 *
4048 * Return: Return the Success or Failure code.
4049 */
4050static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4051 struct wireless_dev *wdev,
4052 const void *data, int data_len)
4053{
4054 int ret;
4055
4056 cds_ssr_protect(__func__);
4057 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4058 cds_ssr_unprotect(__func__);
4059
4060 return ret;
4061}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004062#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063
4064static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4065 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4066 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4067 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004068 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004069};
4070
4071/**
4072 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4073 * @wiphy: pointer to wireless wiphy structure.
4074 * @wdev: pointer to wireless_dev structure.
4075 * @data: Pointer to the data to be passed via vendor interface
4076 * @data_len:Length of the data to be passed
4077 *
4078 * This is called when wlan driver needs to send wifi driver related info
4079 * (driver/fw version) to the user space application upon request.
4080 *
4081 * Return: Return the Success or Failure code.
4082 */
4083static int
4084__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4085 struct wireless_dev *wdev,
4086 const void *data, int data_len)
4087{
4088 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4089 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004090 tSirVersionString driver_version;
4091 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004093 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004094 struct sk_buff *reply_skb;
4095 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004096
Jeff Johnson1f61b612016-02-12 16:28:33 -08004097 ENTER_DEV(wdev->netdev);
4098
Anurag Chouhan6d760662016-02-20 16:05:43 +05304099 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004100 hdd_err("Command not allowed in FTM mode");
4101 return -EPERM;
4102 }
4103
4104 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304105 if (status)
4106 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004107
4108 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4109 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004110 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111 return -EINVAL;
4112 }
4113
4114 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004115 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004116 strlcpy(driver_version, QWLAN_VERSIONSTR,
4117 sizeof(driver_version));
4118 skb_len += strlen(driver_version) + 1;
4119 count++;
4120 }
4121
4122 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004123 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4125 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004126 snprintf(firmware_version, sizeof(firmware_version),
4127 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4128 skb_len += strlen(firmware_version) + 1;
4129 count++;
4130 }
4131
4132 if (count == 0) {
4133 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134 return -EINVAL;
4135 }
4136
Ryan Hsu7ac88852016-04-28 10:20:34 -07004137 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4138 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4139
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004141 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142 return -ENOMEM;
4143 }
4144
Ryan Hsu7ac88852016-04-28 10:20:34 -07004145 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4146 if (nla_put_string(reply_skb,
4147 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4148 driver_version))
4149 goto error_nla_fail;
4150 }
4151
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304152 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004153 if (nla_put_string(reply_skb,
4154 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4155 firmware_version))
4156 goto error_nla_fail;
4157 }
4158
4159 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4160 if (nla_put_u32(reply_skb,
4161 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4162 hdd_ctx->radio_index))
4163 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 }
4165
4166 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004167
4168error_nla_fail:
4169 hdd_err("nla put fail");
4170 kfree_skb(reply_skb);
4171 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004172}
4173
4174/**
4175 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4176 * @wiphy: pointer to wireless wiphy structure.
4177 * @wdev: pointer to wireless_dev structure.
4178 * @data: Pointer to the data to be passed via vendor interface
4179 * @data_len:Length of the data to be passed
4180 *
4181 * This is called when wlan driver needs to send wifi driver related info
4182 * (driver/fw version) to the user space application upon request.
4183 *
4184 * Return: Return the Success or Failure code.
4185 */
4186static int
4187wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4188 struct wireless_dev *wdev,
4189 const void *data, int data_len)
4190{
4191 int ret;
4192
4193 cds_ssr_protect(__func__);
4194 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4195 cds_ssr_unprotect(__func__);
4196
4197 return ret;
4198}
4199
4200/**
4201 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4202 * @wiphy: pointer to wireless wiphy structure.
4203 * @wdev: pointer to wireless_dev structure.
4204 * @data: Pointer to the data to be passed via vendor interface
4205 * @data_len:Length of the data to be passed
4206 *
4207 * This is called by userspace to know the supported logger features
4208 *
4209 * Return: Return the Success or Failure code.
4210 */
4211static int
4212__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4213 struct wireless_dev *wdev,
4214 const void *data, int data_len)
4215{
4216 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4217 int status;
4218 uint32_t features;
4219 struct sk_buff *reply_skb = NULL;
4220
Jeff Johnson1f61b612016-02-12 16:28:33 -08004221 ENTER_DEV(wdev->netdev);
4222
Anurag Chouhan6d760662016-02-20 16:05:43 +05304223 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 hdd_err("Command not allowed in FTM mode");
4225 return -EPERM;
4226 }
4227
4228 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304229 if (status)
4230 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231
4232 features = 0;
4233
4234 if (hdd_is_memdump_supported())
4235 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4236 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4237 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4238 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4239
4240 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4241 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4242 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004243 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004244 return -ENOMEM;
4245 }
4246
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004247 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004248 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4249 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004250 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004251 kfree_skb(reply_skb);
4252 return -EINVAL;
4253 }
4254
4255 return cfg80211_vendor_cmd_reply(reply_skb);
4256}
4257
4258/**
4259 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4260 * @wiphy: pointer to wireless wiphy structure.
4261 * @wdev: pointer to wireless_dev structure.
4262 * @data: Pointer to the data to be passed via vendor interface
4263 * @data_len:Length of the data to be passed
4264 *
4265 * This is called by userspace to know the supported logger features
4266 *
4267 * Return: Return the Success or Failure code.
4268 */
4269static int
4270wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4271 struct wireless_dev *wdev,
4272 const void *data, int data_len)
4273{
4274 int ret;
4275
4276 cds_ssr_protect(__func__);
4277 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4278 data, data_len);
4279 cds_ssr_unprotect(__func__);
4280
4281 return ret;
4282}
4283
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004284#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004285/**
4286 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304287 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004288 * @bssid: pointer to bssid of roamed AP.
4289 * @req_rsn_ie: Pointer to request RSN IE
4290 * @req_rsn_len: Length of the request RSN IE
4291 * @rsp_rsn_ie: Pointer to response RSN IE
4292 * @rsp_rsn_len: Length of the response RSN IE
4293 * @roam_info_ptr: Pointer to the roaming related information
4294 *
4295 * This is called when wlan driver needs to send the roaming and
4296 * authorization information after roaming.
4297 *
4298 * The information that would be sent is the request RSN IE, response
4299 * RSN IE and BSSID of the newly roamed AP.
4300 *
4301 * If the Authorized status is authenticated, then additional parameters
4302 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4303 * supplicant.
4304 *
4305 * The supplicant upon receiving this event would ignore the legacy
4306 * cfg80211_roamed call and use the entire information from this event.
4307 * The cfg80211_roamed should still co-exist since the kernel will
4308 * make use of the parameters even if the supplicant ignores it.
4309 *
4310 * Return: Return the Success or Failure code.
4311 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304312int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4314 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4315{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304316 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004317 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004318 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004319 ENTER();
4320
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304321 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004323
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004324 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004325 !roam_info_ptr->roamSynchInProgress)
4326 return 0;
4327
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004328 /*
4329 * The user space has issued a disconnect when roaming is in
4330 * progress. The disconnect should be honored gracefully.
4331 * If the roaming is complete and the roam event is sent
4332 * back to the user space, it will get confused as it is
4333 * expecting a disconnect event. So, do not send the event
4334 * and handle the disconnect later.
4335 */
4336 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004337 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004338 return 0;
4339 }
4340
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004341 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304342 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004343 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4344 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4345 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004346 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004347 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4348 GFP_KERNEL);
4349
4350 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004351 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004352 return -EINVAL;
4353 }
4354
4355 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4356 ETH_ALEN, bssid) ||
4357 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4358 req_rsn_len, req_rsn_ie) ||
4359 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4360 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004361 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 goto nla_put_failure;
4363 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004364 if (roam_info_ptr->synchAuthStatus ==
4365 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004366 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004367 if (nla_put_u8(skb,
4368 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4369 hdd_err("nla put fail");
4370 goto nla_put_failure;
4371 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004372 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4373 /* if FT or CCKM connection: dont send replay counter */
4374 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4375 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4376 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4377 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4378 nla_put(skb,
4379 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4380 SIR_REPLAY_CTR_LEN,
4381 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004382 hdd_err("non FT/non CCKM connection");
4383 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004384 goto nla_put_failure;
4385 }
4386 if (nla_put(skb,
4387 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4388 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4389 nla_put(skb,
4390 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4391 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4392 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004393 goto nla_put_failure;
4394 }
4395 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004396 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004397 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4398 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004399 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 goto nla_put_failure;
4401 }
4402 }
4403
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304404 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4405 roam_info_ptr->synchAuthStatus,
4406 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004407
4408 /*
4409 * Add subnet change status if subnet has changed
4410 * 0 = unchanged
4411 * 1 = changed
4412 * 2 = unknown
4413 */
4414 if (roam_info_ptr->subnet_change_status) {
4415 if (nla_put_u8(skb,
4416 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4417 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004418 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004419 goto nla_put_failure;
4420 }
4421 }
4422
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004423 cfg80211_vendor_event(skb, GFP_KERNEL);
4424 return 0;
4425
4426nla_put_failure:
4427 kfree_skb(skb);
4428 return -EINVAL;
4429}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004430#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004431
4432static const struct nla_policy
4433wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4434
4435 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4436 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4437 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304438 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304439 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4440 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004441 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4442 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4443 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4444 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4445 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304446 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447};
4448
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004449/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304450 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4451 *
4452 * @adapter: Pointer to HDD adapter
4453 * @ie_data: Pointer to Scan IEs buffer
4454 * @ie_len: Length of Scan IEs
4455 *
4456 * Return: 0 on success; error number otherwise
4457 */
4458static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4459 uint8_t *ie_data, uint8_t ie_len)
4460{
4461 hdd_scaninfo_t *scan_info = NULL;
4462 scan_info = &adapter->scan_info;
4463
4464 if (scan_info->default_scan_ies) {
4465 qdf_mem_free(scan_info->default_scan_ies);
4466 scan_info->default_scan_ies = NULL;
4467 }
4468
4469 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4470 if (!scan_info->default_scan_ies)
4471 return -ENOMEM;
4472
4473 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4474 scan_info->default_scan_ies_len = ie_len;
4475 return 0;
4476}
4477
4478/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4480 * vendor command
4481 *
4482 * @wiphy: wiphy device pointer
4483 * @wdev: wireless device pointer
4484 * @data: Vendor command data buffer
4485 * @data_len: Buffer length
4486 *
4487 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4488 *
4489 * Return: Error code.
4490 */
4491static int
4492__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4493 struct wireless_dev *wdev,
4494 const void *data,
4495 int data_len)
4496{
4497 struct net_device *dev = wdev->netdev;
4498 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4499 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4500 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4501 int ret_val = 0;
4502 u32 modulated_dtim;
4503 u16 stats_avg_factor;
4504 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304505 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004506 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004507 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304508 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304509 int attr_len;
4510 int access_policy = 0;
4511 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4512 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304513 uint16_t scan_ie_len = 0;
4514 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304515 struct sir_set_tx_rx_aggregation_size request;
4516 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004517 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004518 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004519 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304520 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304521
Jeff Johnson1f61b612016-02-12 16:28:33 -08004522 ENTER_DEV(dev);
4523
Anurag Chouhan6d760662016-02-20 16:05:43 +05304524 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004525 hdd_err("Command not allowed in FTM mode");
4526 return -EPERM;
4527 }
4528
4529 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304530 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004531 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004532
4533 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4534 data, data_len,
4535 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004536 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004537 return -EINVAL;
4538 }
4539
Krunal Sonie3531942016-04-12 17:43:53 -07004540 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4541 ftm_capab = nla_get_u32(tb[
4542 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4543 hdd_ctx->config->fine_time_meas_cap =
4544 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4545 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304546 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004547 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004548 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4549 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004550 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004551 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4552 hdd_ctx->config->fine_time_meas_cap);
4553 }
4554
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004555 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4556 modulated_dtim = nla_get_u32(
4557 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4558
4559 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4560 adapter->sessionId,
4561 modulated_dtim);
4562
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304563 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004564 ret_val = -EPERM;
4565 }
4566
Kapil Gupta6213c012016-09-02 19:39:09 +05304567 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4568 qpower = nla_get_u8(
4569 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4570 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4571 ret_val = -EINVAL;
4572 }
4573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004574 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4575 stats_avg_factor = nla_get_u16(
4576 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4577 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4578 adapter->sessionId,
4579 stats_avg_factor);
4580
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304581 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004582 ret_val = -EPERM;
4583 }
4584
4585
4586 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4587 guard_time = nla_get_u32(
4588 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4589 status = sme_configure_guard_time(hdd_ctx->hHal,
4590 adapter->sessionId,
4591 guard_time);
4592
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304593 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004594 ret_val = -EPERM;
4595 }
4596
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304597 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4598 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4599 attr_len = nla_len(
4600 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4601 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004602 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304603 attr_len);
4604 return -EINVAL;
4605 }
4606
4607 nla_memcpy(&vendor_ie,
4608 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4609 attr_len);
4610 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004611 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304612 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304613 }
4614
4615 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4616 access_policy = (int) nla_get_u32(
4617 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4618 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4619 (access_policy >
4620 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004621 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304622 access_policy);
4623 return -EINVAL;
4624 }
4625 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004626 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304627 access_policy);
4628 }
4629
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004630 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4631 retry = nla_get_u8(tb[
4632 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4633 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4634 CFG_NON_AGG_RETRY_MAX : retry;
4635 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4636 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4637 retry, PDEV_CMD);
4638 }
4639
4640 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4641 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4642 retry = retry > CFG_AGG_RETRY_MAX ?
4643 CFG_AGG_RETRY_MAX : retry;
4644
4645 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4646 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4647 CFG_AGG_RETRY_MIN : retry;
4648 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4649 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4650 retry, PDEV_CMD);
4651 }
4652
4653 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4654 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4655 retry = retry > CFG_MGMT_RETRY_MAX ?
4656 CFG_MGMT_RETRY_MAX : retry;
4657 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4658 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4659 retry, PDEV_CMD);
4660 }
4661
4662 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4663 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4664 retry = retry > CFG_CTRL_RETRY_MAX ?
4665 CFG_CTRL_RETRY_MAX : retry;
4666 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4667 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4668 retry, PDEV_CMD);
4669 }
4670
4671 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4672 delay = nla_get_u8(tb[
4673 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4674 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4675 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004676 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004677 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4678 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004679 abs_delay, PDEV_CMD);
4680 }
4681
4682 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4683 abs_delay = nla_get_u8(tb[
4684 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4685 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4686 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4687 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004688 }
4689
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304690 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4691 tx_fail_count = nla_get_u32(
4692 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4693 if (tx_fail_count) {
4694 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4695 adapter->sessionId, tx_fail_count);
4696 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004697 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304698 status);
4699 return -EINVAL;
4700 }
4701 }
4702 }
4703
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304704 if (vendor_ie_present && access_policy_present) {
4705 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4706 access_policy =
4707 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304708 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304709 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304710 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304711
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004712 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304713 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4714 adapter->sessionId, &vendor_ie[0],
4715 access_policy);
4716 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004717 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304718 return -EINVAL;
4719 }
4720 }
4721
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304722 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4723 set_value = nla_get_u8(
4724 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004725 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304726 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4727 }
4728
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304729 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4730 scan_ie_len = nla_len(
4731 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004732 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304733 scan_ie_len, adapter->sessionId,
4734 adapter->device_mode);
4735 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4736 scan_ie = (uint8_t *) nla_data(tb
4737 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304738
4739 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4740 scan_ie_len))
4741 hdd_err("Failed to save default scan IEs");
4742
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304743 if (adapter->device_mode == QDF_STA_MODE) {
4744 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4745 adapter->sessionId, scan_ie,
4746 scan_ie_len);
4747 if (QDF_STATUS_SUCCESS != status)
4748 ret_val = -EPERM;
4749 }
4750 } else
4751 ret_val = -EPERM;
4752 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304753
4754 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4755 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4756 /* if one is specified, both must be specified */
4757 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4758 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4759 hdd_err("Both TX and RX MPDU Aggregation required");
4760 return -EINVAL;
4761 }
4762
4763 request.tx_aggregation_size = nla_get_u8(
4764 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4765 request.rx_aggregation_size = nla_get_u8(
4766 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4767 request.vdev_id = adapter->sessionId;
4768
4769 if (request.tx_aggregation_size >=
4770 CFG_TX_AGGREGATION_SIZE_MIN &&
4771 request.tx_aggregation_size <=
4772 CFG_TX_AGGREGATION_SIZE_MAX &&
4773 request.rx_aggregation_size >=
4774 CFG_RX_AGGREGATION_SIZE_MIN &&
4775 request.rx_aggregation_size <=
4776 CFG_RX_AGGREGATION_SIZE_MAX) {
4777 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4778 if (qdf_status != QDF_STATUS_SUCCESS) {
4779 hdd_err("failed to set aggr sizes err %d",
4780 qdf_status);
4781 ret_val = -EPERM;
4782 }
4783 } else {
4784 hdd_err("TX %d RX %d MPDU aggr size not in range",
4785 request.tx_aggregation_size,
4786 request.rx_aggregation_size);
4787 ret_val = -EINVAL;
4788 }
4789 }
4790
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304791 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4792 uint8_t ignore_assoc_disallowed;
4793
4794 ignore_assoc_disallowed
4795 = nla_get_u8(tb[
4796 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004797 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304798 ignore_assoc_disallowed);
4799 if ((ignore_assoc_disallowed <
4800 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4801 (ignore_assoc_disallowed >
4802 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4803 return -EPERM;
4804
4805 sme_update_session_param(hdd_ctx->hHal,
4806 adapter->sessionId,
4807 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4808 ignore_assoc_disallowed);
4809 }
4810
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004811 return ret_val;
4812}
4813
4814/**
4815 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4816 * vendor command
4817 *
4818 * @wiphy: wiphy device pointer
4819 * @wdev: wireless device pointer
4820 * @data: Vendor command data buffer
4821 * @data_len: Buffer length
4822 *
4823 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4824 *
4825 * Return: EOK or other error codes.
4826 */
4827static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4828 struct wireless_dev *wdev,
4829 const void *data,
4830 int data_len)
4831{
4832 int ret;
4833
4834 cds_ssr_protect(__func__);
4835 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4836 data, data_len);
4837 cds_ssr_unprotect(__func__);
4838
4839 return ret;
4840}
4841
4842static const struct
4843nla_policy
4844qca_wlan_vendor_wifi_logger_start_policy
4845[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4846 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4847 = {.type = NLA_U32 },
4848 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4849 = {.type = NLA_U32 },
4850 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4851 = {.type = NLA_U32 },
4852};
4853
4854/**
4855 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4856 * or disable the collection of packet statistics from the firmware
4857 * @wiphy: WIPHY structure pointer
4858 * @wdev: Wireless device structure pointer
4859 * @data: Pointer to the data received
4860 * @data_len: Length of the data received
4861 *
4862 * This function enables or disables the collection of packet statistics from
4863 * the firmware
4864 *
4865 * Return: 0 on success and errno on failure
4866 */
4867static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4868 struct wireless_dev *wdev,
4869 const void *data,
4870 int data_len)
4871{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304872 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4874 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4875 struct sir_wifi_start_log start_log;
4876
Jeff Johnson1f61b612016-02-12 16:28:33 -08004877 ENTER_DEV(wdev->netdev);
4878
Anurag Chouhan6d760662016-02-20 16:05:43 +05304879 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 hdd_err("Command not allowed in FTM mode");
4881 return -EPERM;
4882 }
4883
4884 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304885 if (status)
4886 return status;
4887
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304888 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4889 hdd_err("Driver Modules are closed, can not start logger");
4890 return -EINVAL;
4891 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004892
4893 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4894 data, data_len,
4895 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004896 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004897 return -EINVAL;
4898 }
4899
4900 /* Parse and fetch ring id */
4901 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004902 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004903 return -EINVAL;
4904 }
4905 start_log.ring_id = nla_get_u32(
4906 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004907 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908
4909 /* Parse and fetch verbose level */
4910 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004911 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004912 return -EINVAL;
4913 }
4914 start_log.verbose_level = nla_get_u32(
4915 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004916 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917
4918 /* Parse and fetch flag */
4919 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004920 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921 return -EINVAL;
4922 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304923 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004924 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004925 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004926
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304927 /* size is buff size which can be set using iwpriv command*/
4928 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05304929 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4932
4933 if (start_log.ring_id == RING_ID_WAKELOCK) {
4934 /* Start/stop wakelock events */
4935 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4936 cds_set_wakelock_logging(true);
4937 else
4938 cds_set_wakelock_logging(false);
4939 return 0;
4940 }
4941
4942 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304943 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004944 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004945 status);
4946 return -EINVAL;
4947 }
4948 return 0;
4949}
4950
4951/**
4952 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4953 * or disable the collection of packet statistics from the firmware
4954 * @wiphy: WIPHY structure pointer
4955 * @wdev: Wireless device structure pointer
4956 * @data: Pointer to the data received
4957 * @data_len: Length of the data received
4958 *
4959 * This function is used to enable or disable the collection of packet
4960 * statistics from the firmware
4961 *
4962 * Return: 0 on success and errno on failure
4963 */
4964static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4965 struct wireless_dev *wdev,
4966 const void *data,
4967 int data_len)
4968{
4969 int ret = 0;
4970
4971 cds_ssr_protect(__func__);
4972 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4973 wdev, data, data_len);
4974 cds_ssr_unprotect(__func__);
4975
4976 return ret;
4977}
4978
4979static const struct
4980nla_policy
4981qca_wlan_vendor_wifi_logger_get_ring_data_policy
4982[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4983 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4984 = {.type = NLA_U32 },
4985};
4986
4987/**
4988 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4989 * @wiphy: WIPHY structure pointer
4990 * @wdev: Wireless device structure pointer
4991 * @data: Pointer to the data received
4992 * @data_len: Length of the data received
4993 *
4994 * This function is used to flush or retrieve the per packet statistics from
4995 * the driver
4996 *
4997 * Return: 0 on success and errno on failure
4998 */
4999static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5000 struct wireless_dev *wdev,
5001 const void *data,
5002 int data_len)
5003{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305004 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 uint32_t ring_id;
5006 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5007 struct nlattr *tb
5008 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5009
Jeff Johnson1f61b612016-02-12 16:28:33 -08005010 ENTER_DEV(wdev->netdev);
5011
Anurag Chouhan6d760662016-02-20 16:05:43 +05305012 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013 hdd_err("Command not allowed in FTM mode");
5014 return -EPERM;
5015 }
5016
5017 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305018 if (status)
5019 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020
5021 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5022 data, data_len,
5023 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005024 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005025 return -EINVAL;
5026 }
5027
5028 /* Parse and fetch ring id */
5029 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005030 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005031 return -EINVAL;
5032 }
5033
5034 ring_id = nla_get_u32(
5035 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5036
5037 if (ring_id == RING_ID_PER_PACKET_STATS) {
5038 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005039 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305040 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5041 /*
5042 * As part of DRIVER ring ID, flush both driver and fw logs.
5043 * For other Ring ID's driver doesn't have any rings to flush
5044 */
5045 hdd_notice("Bug report triggered by framework");
5046
5047 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5048 WLAN_LOG_INDICATOR_FRAMEWORK,
5049 WLAN_LOG_REASON_CODE_UNUSED,
5050 true, false);
5051 if (QDF_STATUS_SUCCESS != status) {
5052 hdd_err("Failed to trigger bug report");
5053 return -EINVAL;
5054 }
5055 } else {
5056 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5057 WLAN_LOG_INDICATOR_FRAMEWORK,
5058 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005059 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005060 return 0;
5061}
5062
5063/**
5064 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5065 * @wiphy: WIPHY structure pointer
5066 * @wdev: Wireless device structure pointer
5067 * @data: Pointer to the data received
5068 * @data_len: Length of the data received
5069 *
5070 * This function is used to flush or retrieve the per packet statistics from
5071 * the driver
5072 *
5073 * Return: 0 on success and errno on failure
5074 */
5075static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5076 struct wireless_dev *wdev,
5077 const void *data,
5078 int data_len)
5079{
5080 int ret = 0;
5081
5082 cds_ssr_protect(__func__);
5083 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5084 wdev, data, data_len);
5085 cds_ssr_unprotect(__func__);
5086
5087 return ret;
5088}
5089
5090#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5091/**
5092 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5093 * @hdd_ctx: HDD context
5094 * @request_id: [input] request id
5095 * @pattern_id: [output] pattern id
5096 *
5097 * This function loops through request id to pattern id array
5098 * if the slot is available, store the request id and return pattern id
5099 * if entry exists, return the pattern id
5100 *
5101 * Return: 0 on success and errno on failure
5102 */
5103static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5104 uint32_t request_id,
5105 uint8_t *pattern_id)
5106{
5107 uint32_t i;
5108
5109 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5110 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5111 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5112 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5113 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5114 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5115 return 0;
5116 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5117 request_id) {
5118 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5119 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5120 return 0;
5121 }
5122 }
5123 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5124 return -EINVAL;
5125}
5126
5127/**
5128 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5129 * @hdd_ctx: HDD context
5130 * @request_id: [input] request id
5131 * @pattern_id: [output] pattern id
5132 *
5133 * This function loops through request id to pattern id array
5134 * reset request id to 0 (slot available again) and
5135 * return pattern id
5136 *
5137 * Return: 0 on success and errno on failure
5138 */
5139static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5140 uint32_t request_id,
5141 uint8_t *pattern_id)
5142{
5143 uint32_t i;
5144
5145 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5146 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5147 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5148 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5149 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5150 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5151 return 0;
5152 }
5153 }
5154 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5155 return -EINVAL;
5156}
5157
5158
5159/*
5160 * define short names for the global vendor params
5161 * used by __wlan_hdd_cfg80211_offloaded_packets()
5162 */
5163#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5164#define PARAM_REQUEST_ID \
5165 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5166#define PARAM_CONTROL \
5167 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5168#define PARAM_IP_PACKET \
5169 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5170#define PARAM_SRC_MAC_ADDR \
5171 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5172#define PARAM_DST_MAC_ADDR \
5173 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5174#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5175
5176/**
5177 * wlan_hdd_add_tx_ptrn() - add tx pattern
5178 * @adapter: adapter pointer
5179 * @hdd_ctx: hdd context
5180 * @tb: nl attributes
5181 *
5182 * This function reads the NL attributes and forms a AddTxPtrn message
5183 * posts it to SME.
5184 *
5185 */
5186static int
5187wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5188 struct nlattr **tb)
5189{
5190 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305191 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192 uint32_t request_id, ret, len;
5193 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305194 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195 uint16_t eth_type = htons(ETH_P_IP);
5196
5197 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005198 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 return -ENOTSUPP;
5200 }
5201
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305202 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005204 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005205 return -ENOMEM;
5206 }
5207
5208 /* Parse and fetch request Id */
5209 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005210 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 goto fail;
5212 }
5213
5214 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5215 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005216 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005217 return -EINVAL;
5218 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005219 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005220
5221 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005222 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223 goto fail;
5224 }
5225 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005226 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005227 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005228 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005229 goto fail;
5230 }
5231
5232 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005233 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 goto fail;
5235 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005236 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305237 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005238 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005239 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005240
Anurag Chouhanc5548422016-02-24 18:33:27 +05305241 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005242 &adapter->macAddressCurrent)) {
5243 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005244 goto fail;
5245 }
5246
5247 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005248 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005249 goto fail;
5250 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305251 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005252 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005253 MAC_ADDR_ARRAY(dst_addr.bytes));
5254
5255 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005256 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257 goto fail;
5258 }
5259 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005260 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005261
5262 if (add_req->ucPtrnSize < 0 ||
5263 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5264 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005265 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266 add_req->ucPtrnSize);
5267 goto fail;
5268 }
5269
5270 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305271 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305272 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305273 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305274 QDF_MAC_ADDR_SIZE);
5275 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305276 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005277 len += 2;
5278
5279 /*
5280 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5281 * ------------------------------------------------------------
5282 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5283 * ------------------------------------------------------------
5284 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305285 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005286 nla_data(tb[PARAM_IP_PACKET]),
5287 add_req->ucPtrnSize);
5288 add_req->ucPtrnSize += len;
5289
5290 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5291 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005292 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293 goto fail;
5294 }
5295 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005296 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297
5298 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305299 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005300 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005301 goto fail;
5302 }
5303
5304 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305305 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005306 return 0;
5307
5308fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305309 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005310 return -EINVAL;
5311}
5312
5313/**
5314 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5315 * @adapter: adapter pointer
5316 * @hdd_ctx: hdd context
5317 * @tb: nl attributes
5318 *
5319 * This function reads the NL attributes and forms a DelTxPtrn message
5320 * posts it to SME.
5321 *
5322 */
5323static int
5324wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5325 struct nlattr **tb)
5326{
5327 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305328 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005329 uint32_t request_id, ret;
5330 uint8_t pattern_id = 0;
5331
5332 /* Parse and fetch request Id */
5333 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005334 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005335 return -EINVAL;
5336 }
5337 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5338 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005339 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 return -EINVAL;
5341 }
5342
5343 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5344 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005345 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346 return -EINVAL;
5347 }
5348
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305349 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005350 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005351 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005352 return -ENOMEM;
5353 }
5354
Anurag Chouhanc5548422016-02-24 18:33:27 +05305355 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005356 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005358 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 request_id, del_req->ucPtrnId);
5360
5361 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305362 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005363 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364 goto fail;
5365 }
5366
5367 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305368 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005369 return 0;
5370
5371fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305372 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373 return -EINVAL;
5374}
5375
5376
5377/**
5378 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5379 * @wiphy: Pointer to wireless phy
5380 * @wdev: Pointer to wireless device
5381 * @data: Pointer to data
5382 * @data_len: Data length
5383 *
5384 * Return: 0 on success, negative errno on failure
5385 */
5386static int
5387__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5388 struct wireless_dev *wdev,
5389 const void *data,
5390 int data_len)
5391{
5392 struct net_device *dev = wdev->netdev;
5393 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5394 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5395 struct nlattr *tb[PARAM_MAX + 1];
5396 uint8_t control;
5397 int ret;
5398 static const struct nla_policy policy[PARAM_MAX + 1] = {
5399 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5400 [PARAM_CONTROL] = { .type = NLA_U32 },
5401 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305402 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005403 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305404 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005405 [PARAM_PERIOD] = { .type = NLA_U32 },
5406 };
5407
Jeff Johnson1f61b612016-02-12 16:28:33 -08005408 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005409
Anurag Chouhan6d760662016-02-20 16:05:43 +05305410 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411 hdd_err("Command not allowed in FTM mode");
5412 return -EPERM;
5413 }
5414
5415 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305416 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418
5419 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005420 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 return -ENOTSUPP;
5422 }
5423
5424 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005425 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 return -EINVAL;
5427 }
5428
5429 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005430 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 return -EINVAL;
5432 }
5433 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005434 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005435
5436 if (control == WLAN_START_OFFLOADED_PACKETS)
5437 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005438 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005440
5441 hdd_err("Invalid control: %d", control);
5442
5443 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005444}
5445
5446/*
5447 * done with short names for the global vendor params
5448 * used by __wlan_hdd_cfg80211_offloaded_packets()
5449 */
5450#undef PARAM_MAX
5451#undef PARAM_REQUEST_ID
5452#undef PARAM_CONTROL
5453#undef PARAM_IP_PACKET
5454#undef PARAM_SRC_MAC_ADDR
5455#undef PARAM_DST_MAC_ADDR
5456#undef PARAM_PERIOD
5457
5458/**
5459 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5460 * @wiphy: wiphy structure pointer
5461 * @wdev: Wireless device structure pointer
5462 * @data: Pointer to the data received
5463 * @data_len: Length of @data
5464 *
5465 * Return: 0 on success; errno on failure
5466 */
5467static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5468 struct wireless_dev *wdev,
5469 const void *data,
5470 int data_len)
5471{
5472 int ret = 0;
5473
5474 cds_ssr_protect(__func__);
5475 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5476 wdev, data, data_len);
5477 cds_ssr_unprotect(__func__);
5478
5479 return ret;
5480}
5481#endif
5482
5483/*
5484 * define short names for the global vendor params
5485 * used by __wlan_hdd_cfg80211_monitor_rssi()
5486 */
5487#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5488#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5489#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5490#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5491#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5492
5493/**
5494 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5495 * @wiphy: Pointer to wireless phy
5496 * @wdev: Pointer to wireless device
5497 * @data: Pointer to data
5498 * @data_len: Data length
5499 *
5500 * Return: 0 on success, negative errno on failure
5501 */
5502static int
5503__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5504 struct wireless_dev *wdev,
5505 const void *data,
5506 int data_len)
5507{
5508 struct net_device *dev = wdev->netdev;
5509 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5510 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5511 struct nlattr *tb[PARAM_MAX + 1];
5512 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305513 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005514 int ret;
5515 uint32_t control;
5516 static const struct nla_policy policy[PARAM_MAX + 1] = {
5517 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5518 [PARAM_CONTROL] = { .type = NLA_U32 },
5519 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5520 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5521 };
5522
Jeff Johnson1f61b612016-02-12 16:28:33 -08005523 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005524
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305525 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5526 hdd_err("invalid session id: %d", adapter->sessionId);
5527 return -EINVAL;
5528 }
5529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305531 if (ret)
5532 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005533
5534 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005535 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536 return -ENOTSUPP;
5537 }
5538
5539 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005540 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005541 return -EINVAL;
5542 }
5543
5544 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005545 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546 return -EINVAL;
5547 }
5548
5549 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005550 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005551 return -EINVAL;
5552 }
5553
5554 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5555 req.session_id = adapter->sessionId;
5556 control = nla_get_u32(tb[PARAM_CONTROL]);
5557
5558 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5559 req.control = true;
5560 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005561 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005562 return -EINVAL;
5563 }
5564
5565 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005566 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005567 return -EINVAL;
5568 }
5569
5570 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5571 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5572
5573 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005574 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 req.min_rssi, req.max_rssi);
5576 return -EINVAL;
5577 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005578 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579 req.min_rssi, req.max_rssi);
5580
5581 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5582 req.control = false;
5583 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005584 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005585 return -EINVAL;
5586 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005587 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005588 req.request_id, req.session_id, req.control);
5589
5590 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305591 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005592 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593 return -EINVAL;
5594 }
5595
5596 return 0;
5597}
5598
5599/*
5600 * done with short names for the global vendor params
5601 * used by __wlan_hdd_cfg80211_monitor_rssi()
5602 */
5603#undef PARAM_MAX
5604#undef PARAM_CONTROL
5605#undef PARAM_REQUEST_ID
5606#undef PARAM_MAX_RSSI
5607#undef PARAM_MIN_RSSI
5608
5609/**
5610 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5611 * @wiphy: wiphy structure pointer
5612 * @wdev: Wireless device structure pointer
5613 * @data: Pointer to the data received
5614 * @data_len: Length of @data
5615 *
5616 * Return: 0 on success; errno on failure
5617 */
5618static int
5619wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5620 const void *data, int data_len)
5621{
5622 int ret;
5623
5624 cds_ssr_protect(__func__);
5625 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5626 cds_ssr_unprotect(__func__);
5627
5628 return ret;
5629}
5630
5631/**
5632 * hdd_rssi_threshold_breached() - rssi breached NL event
5633 * @hddctx: HDD context
5634 * @data: rssi breached event data
5635 *
5636 * This function reads the rssi breached event %data and fill in the skb with
5637 * NL attributes and send up the NL event.
5638 *
5639 * Return: none
5640 */
5641void hdd_rssi_threshold_breached(void *hddctx,
5642 struct rssi_breach_event *data)
5643{
5644 hdd_context_t *hdd_ctx = hddctx;
5645 struct sk_buff *skb;
5646
5647 ENTER();
5648
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305649 if (wlan_hdd_validate_context(hdd_ctx))
5650 return;
5651 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005652 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005653 return;
5654 }
5655
5656 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5657 NULL,
5658 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5659 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5660 GFP_KERNEL);
5661
5662 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005663 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005664 return;
5665 }
5666
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005667 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005668 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005669 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005670 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5671
5672 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5673 data->request_id) ||
5674 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5675 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5676 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5677 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005678 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005679 goto fail;
5680 }
5681
5682 cfg80211_vendor_event(skb, GFP_KERNEL);
5683 return;
5684
5685fail:
5686 kfree_skb(skb);
5687 return;
5688}
5689
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305690static const struct nla_policy
5691ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5692 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5693};
5694
5695/**
5696 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5697 * @wiphy: Pointer to wireless phy
5698 * @wdev: Pointer to wireless device
5699 * @data: Pointer to data
5700 * @data_len: Length of @data
5701 *
5702 * Return: 0 on success, negative errno on failure
5703 */
5704static int
5705__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5706 struct wireless_dev *wdev,
5707 const void *data, int data_len)
5708{
5709 int status;
5710 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5711 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005712 struct net_device *dev = wdev->netdev;
5713 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305714
5715 ENTER_DEV(wdev->netdev);
5716
5717 status = wlan_hdd_validate_context(pHddCtx);
5718 if (0 != status)
5719 return status;
5720 if (!pHddCtx->config->fhostNSOffload) {
5721 hdd_err("ND Offload not supported");
5722 return -EINVAL;
5723 }
5724
5725 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5726 (struct nlattr *)data,
5727 data_len, ns_offload_set_policy)) {
5728 hdd_err("nla_parse failed");
5729 return -EINVAL;
5730 }
5731
5732 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5733 hdd_err("ND Offload flag attribute not present");
5734 return -EINVAL;
5735 }
5736
5737 pHddCtx->ns_offload_enable =
5738 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5739
Dustin Brownd8279d22016-09-07 14:52:57 -07005740 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305741 if (pHddCtx->ns_offload_enable)
5742 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5743 else
5744 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005745
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305746 return 0;
5747}
5748
5749/**
5750 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5751 * @wiphy: pointer to wireless wiphy structure.
5752 * @wdev: pointer to wireless_dev structure.
5753 * @data: Pointer to the data to be passed via vendor interface
5754 * @data_len:Length of the data to be passed
5755 *
5756 * Return: Return the Success or Failure code.
5757 */
5758static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5759 struct wireless_dev *wdev,
5760 const void *data, int data_len)
5761{
5762 int ret;
5763
5764 cds_ssr_protect(__func__);
5765 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5766 cds_ssr_unprotect(__func__);
5767
5768 return ret;
5769}
5770
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5772 * @wiphy: Pointer to wireless phy
5773 * @wdev: Pointer to wireless device
5774 * @data: Pointer to data
5775 * @data_len: Data length
5776 *
5777 * This function return the preferred frequency list generated by the policy
5778 * manager.
5779 *
5780 * Return: success or failure code
5781 */
5782static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5783 struct wireless_dev
5784 *wdev, const void *data,
5785 int data_len)
5786{
5787 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5788 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305789 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305790 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305792 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005793 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5795 struct sk_buff *reply_skb;
5796
Jeff Johnson1f61b612016-02-12 16:28:33 -08005797 ENTER_DEV(wdev->netdev);
5798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799 ret = wlan_hdd_validate_context(hdd_ctx);
5800 if (ret)
5801 return -EINVAL;
5802
5803 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5804 data, data_len, NULL)) {
5805 hdd_err("Invalid ATTR");
5806 return -EINVAL;
5807 }
5808
5809 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5810 hdd_err("attr interface type failed");
5811 return -EINVAL;
5812 }
5813
5814 intf_mode = nla_get_u32(tb
5815 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5816
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005817 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005818 hdd_err("Invalid interface type");
5819 return -EINVAL;
5820 }
5821
5822 hdd_debug("Userspace requested pref freq list");
5823
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005824 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5825 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305826 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305827 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005828 hdd_err("Get pcl failed");
5829 return -EINVAL;
5830 }
5831
5832 /* convert channel number to frequency */
5833 for (i = 0; i < pcl_len; i++) {
5834 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5835 freq_list[i] =
5836 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005837 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838 else
5839 freq_list[i] =
5840 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005841 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005842 }
5843
5844 /* send the freq_list back to supplicant */
5845 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5846 sizeof(u32) *
5847 pcl_len +
5848 NLMSG_HDRLEN);
5849
5850 if (!reply_skb) {
5851 hdd_err("Allocate reply_skb failed");
5852 return -EINVAL;
5853 }
5854
5855 if (nla_put_u32(reply_skb,
5856 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5857 intf_mode) ||
5858 nla_put(reply_skb,
5859 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5860 sizeof(uint32_t) * pcl_len,
5861 freq_list)) {
5862 hdd_err("nla put fail");
5863 kfree_skb(reply_skb);
5864 return -EINVAL;
5865 }
5866
5867 return cfg80211_vendor_cmd_reply(reply_skb);
5868}
5869
5870/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5871 * @wiphy: Pointer to wireless phy
5872 * @wdev: Pointer to wireless device
5873 * @data: Pointer to data
5874 * @data_len: Data length
5875 *
5876 * This function return the preferred frequency list generated by the policy
5877 * manager.
5878 *
5879 * Return: success or failure code
5880 */
5881static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5882 struct wireless_dev
5883 *wdev, const void *data,
5884 int data_len)
5885{
5886 int ret = 0;
5887
5888 cds_ssr_protect(__func__);
5889 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5890 data, data_len);
5891 cds_ssr_unprotect(__func__);
5892
5893 return ret;
5894}
5895
5896/**
5897 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5898 * @wiphy: Pointer to wireless phy
5899 * @wdev: Pointer to wireless device
5900 * @data: Pointer to data
5901 * @data_len: Data length
5902 *
5903 * Return: 0 on success, negative errno on failure
5904 */
5905static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5906 struct wireless_dev *wdev,
5907 const void *data,
5908 int data_len)
5909{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305910 struct net_device *ndev = wdev->netdev;
5911 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005912 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5913 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005914 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5916 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005917
Jeff Johnson1f61b612016-02-12 16:28:33 -08005918 ENTER_DEV(ndev);
5919
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005920 ret = wlan_hdd_validate_context(hdd_ctx);
5921 if (ret)
5922 return ret;
5923
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005924 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5925 data, data_len, NULL)) {
5926 hdd_err("Invalid ATTR");
5927 return -EINVAL;
5928 }
5929
5930 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5931 hdd_err("attr interface type failed");
5932 return -EINVAL;
5933 }
5934
5935 intf_mode = nla_get_u32(tb
5936 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5937
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005938 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005939 hdd_err("Invalid interface type");
5940 return -EINVAL;
5941 }
5942
5943 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5944 hdd_err("attr probable freq failed");
5945 return -EINVAL;
5946 }
5947
5948 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5949 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5950
5951 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005952 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005953 channel_hint, HW_MODE_20_MHZ)) {
5954 hdd_err("Set channel hint failed due to concurrency check");
5955 return -EINVAL;
5956 }
5957
Krunal Soni09e55032016-06-07 10:06:55 -07005958 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5959 hdd_warn("Remain On Channel Pending");
5960
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005961 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005962 if (!QDF_IS_STATUS_SUCCESS(ret))
5963 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005964
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005965 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
5966 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07005967 SIR_UPDATE_REASON_SET_OPER_CHAN);
5968 if (QDF_STATUS_E_FAILURE == ret) {
5969 /* return in the failure case */
5970 hdd_err("ERROR: connections update failed!!");
5971 return -EINVAL;
5972 }
5973
5974 if (QDF_STATUS_SUCCESS == ret) {
5975 /*
5976 * Success is the only case for which we expect hw mode
5977 * change to take place, hence we need to wait.
5978 * For any other return value it should be a pass
5979 * through
5980 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005981 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005982 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5983 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005984 return -EINVAL;
5985 }
5986
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005987 }
5988
5989 return 0;
5990}
5991
5992/**
5993 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5994 * @wiphy: Pointer to wireless phy
5995 * @wdev: Pointer to wireless device
5996 * @data: Pointer to data
5997 * @data_len: Data length
5998 *
5999 * Return: 0 on success, negative errno on failure
6000 */
6001static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6002 struct wireless_dev *wdev,
6003 const void *data,
6004 int data_len)
6005{
6006 int ret = 0;
6007
6008 cds_ssr_protect(__func__);
6009 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6010 data, data_len);
6011 cds_ssr_unprotect(__func__);
6012
6013 return ret;
6014}
6015
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306016static const struct
6017nla_policy
6018qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6019 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6020};
6021
6022/**
6023 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6024 * @wiphy: WIPHY structure pointer
6025 * @wdev: Wireless device structure pointer
6026 * @data: Pointer to the data received
6027 * @data_len: Length of the data received
6028 *
6029 * This function is used to get link properties like nss, rate flags and
6030 * operating frequency for the active connection with the given peer.
6031 *
6032 * Return: 0 on success and errno on failure
6033 */
6034static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6035 struct wireless_dev *wdev,
6036 const void *data,
6037 int data_len)
6038{
6039 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6040 struct net_device *dev = wdev->netdev;
6041 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6042 hdd_station_ctx_t *hdd_sta_ctx;
6043 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306044 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306045 uint32_t sta_id;
6046 struct sk_buff *reply_skb;
6047 uint32_t rate_flags = 0;
6048 uint8_t nss;
6049 uint8_t final_rate_flags = 0;
6050 uint32_t freq;
6051
Jeff Johnson1f61b612016-02-12 16:28:33 -08006052 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306053
Anurag Chouhan6d760662016-02-20 16:05:43 +05306054 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306055 hdd_err("Command not allowed in FTM mode");
6056 return -EPERM;
6057 }
6058
6059 if (0 != wlan_hdd_validate_context(hdd_ctx))
6060 return -EINVAL;
6061
6062 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6063 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006064 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306065 return -EINVAL;
6066 }
6067
6068 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006069 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306070 adapter->device_mode);
6071 return -EINVAL;
6072 }
6073
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306074 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306075 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006076 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306077 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6078
Krunal Sonib4326f22016-03-10 13:05:51 -08006079 if (adapter->device_mode == QDF_STA_MODE ||
6080 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306081 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6082 if ((hdd_sta_ctx->conn_info.connState !=
6083 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306084 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306085 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006086 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306087 MAC_ADDR_ARRAY(peer_mac));
6088 return -EINVAL;
6089 }
6090
6091 nss = hdd_sta_ctx->conn_info.nss;
6092 freq = cds_chan_to_freq(
6093 hdd_sta_ctx->conn_info.operationChannel);
6094 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006095 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6096 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306097
6098 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6099 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306100 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306101 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306102 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306103 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306104 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306105 break;
6106 }
6107
6108 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006109 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306110 MAC_ADDR_ARRAY(peer_mac));
6111 return -EINVAL;
6112 }
6113
6114 nss = adapter->aStaInfo[sta_id].nss;
6115 freq = cds_chan_to_freq(
6116 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6117 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6118 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006119 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306120 MAC_ADDR_ARRAY(peer_mac));
6121 return -EINVAL;
6122 }
6123
6124 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6125 if (rate_flags & eHAL_TX_RATE_VHT80) {
6126 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006127#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306128 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006129#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306130 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6131 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006132#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306133 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006134#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306135 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6136 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6137 } else if (rate_flags &
6138 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6139 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006140#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306141 if (rate_flags & eHAL_TX_RATE_HT40)
6142 final_rate_flags |=
6143 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006144#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306145 }
6146
6147 if (rate_flags & eHAL_TX_RATE_SGI) {
6148 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6149 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6150 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6151 }
6152 }
6153
6154 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6155 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6156
6157 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006158 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306159 return -EINVAL;
6160 }
6161
6162 if (nla_put_u8(reply_skb,
6163 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6164 nss) ||
6165 nla_put_u8(reply_skb,
6166 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6167 final_rate_flags) ||
6168 nla_put_u32(reply_skb,
6169 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6170 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006171 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306172 kfree_skb(reply_skb);
6173 return -EINVAL;
6174 }
6175
6176 return cfg80211_vendor_cmd_reply(reply_skb);
6177}
6178
6179/**
6180 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6181 * properties.
6182 * @wiphy: WIPHY structure pointer
6183 * @wdev: Wireless device structure pointer
6184 * @data: Pointer to the data received
6185 * @data_len: Length of the data received
6186 *
6187 * This function is used to get link properties like nss, rate flags and
6188 * operating frequency for the active connection with the given peer.
6189 *
6190 * Return: 0 on success and errno on failure
6191 */
6192static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6193 struct wireless_dev *wdev,
6194 const void *data,
6195 int data_len)
6196{
6197 int ret = 0;
6198
6199 cds_ssr_protect(__func__);
6200 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6201 wdev, data, data_len);
6202 cds_ssr_unprotect(__func__);
6203
6204 return ret;
6205}
6206
Peng Xu278d0122015-09-24 16:34:17 -07006207static const struct
6208nla_policy
6209qca_wlan_vendor_ota_test_policy
6210[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6211 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6212};
6213
6214/**
6215 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6216 * @wiphy: Pointer to wireless phy
6217 * @wdev: Pointer to wireless device
6218 * @data: Pointer to data
6219 * @data_len: Data length
6220 *
6221 * Return: 0 on success, negative errno on failure
6222 */
6223static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6224 struct wireless_dev *wdev,
6225 const void *data,
6226 int data_len)
6227{
6228 struct net_device *dev = wdev->netdev;
6229 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6230 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6231 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6232 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6233 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306234 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006235 uint32_t current_roam_state;
6236
Jeff Johnson1f61b612016-02-12 16:28:33 -08006237 ENTER_DEV(dev);
6238
Anurag Chouhan6d760662016-02-20 16:05:43 +05306239 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006240 hdd_err("Command not allowed in FTM mode");
6241 return -EPERM;
6242 }
6243
6244 if (0 != wlan_hdd_validate_context(hdd_ctx))
6245 return -EINVAL;
6246
6247 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6248 data, data_len,
6249 qca_wlan_vendor_ota_test_policy)) {
6250 hdd_err("invalid attr");
6251 return -EINVAL;
6252 }
6253
6254 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6255 hdd_err("attr ota test failed");
6256 return -EINVAL;
6257 }
6258
6259 ota_enable = nla_get_u8(
6260 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6261
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006262 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006263 if (ota_enable != 1) {
6264 hdd_err("Invalid value, only enable test mode is supported!");
6265 return -EINVAL;
6266 }
6267
6268 current_roam_state =
6269 sme_get_current_roam_state(hal, adapter->sessionId);
6270 status = sme_stop_roaming(hal, adapter->sessionId,
6271 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306272 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006273 hdd_err("Enable/Disable roaming failed");
6274 return -EINVAL;
6275 }
6276
6277 status = sme_ps_enable_disable(hal, adapter->sessionId,
6278 SME_PS_DISABLE);
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 power save failed");
6281 /* restore previous roaming setting */
6282 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6283 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6284 status = sme_start_roaming(hal, adapter->sessionId,
6285 eCsrHddIssued);
6286 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6287 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6288 status = sme_stop_roaming(hal, adapter->sessionId,
6289 eCsrHddIssued);
6290
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306291 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006292 hdd_err("Restoring roaming state failed");
6293
6294 return -EINVAL;
6295 }
6296
6297
6298 return 0;
6299}
6300
6301/**
6302 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6303 * @wiphy: Pointer to wireless phy
6304 * @wdev: Pointer to wireless device
6305 * @data: Pointer to data
6306 * @data_len: Data length
6307 *
6308 * Return: 0 on success, negative errno on failure
6309 */
6310static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6311 struct wireless_dev *wdev,
6312 const void *data,
6313 int data_len)
6314{
6315 int ret = 0;
6316
6317 cds_ssr_protect(__func__);
6318 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6319 cds_ssr_unprotect(__func__);
6320
6321 return ret;
6322}
6323
Peng Xu4d67c8f2015-10-16 16:02:26 -07006324/**
6325 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6326 * @wiphy: Pointer to wireless phy
6327 * @wdev: Pointer to wireless device
6328 * @data: Pointer to data
6329 * @data_len: Data length
6330 *
6331 * Return: 0 on success, negative errno on failure
6332 */
6333static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6334 struct wireless_dev *wdev,
6335 const void *data,
6336 int data_len)
6337{
6338 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6339 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006340 hdd_adapter_t *adapter;
6341 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006342 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6343 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006344 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006345
Jeff Johnson1f61b612016-02-12 16:28:33 -08006346 ENTER_DEV(dev);
6347
Peng Xu4d67c8f2015-10-16 16:02:26 -07006348 ret = wlan_hdd_validate_context(hdd_ctx);
6349 if (ret)
6350 return ret;
6351
6352 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6353
6354 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6355 data, data_len, NULL)) {
6356 hdd_err("Invalid ATTR");
6357 return -EINVAL;
6358 }
6359
6360 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6361 hdd_err("attr tx power scale failed");
6362 return -EINVAL;
6363 }
6364
6365 scale_value = nla_get_u8(tb
6366 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6367
6368 if (scale_value > MAX_TXPOWER_SCALE) {
6369 hdd_err("Invalid tx power scale level");
6370 return -EINVAL;
6371 }
6372
Peng Xu62c8c432016-05-09 15:23:02 -07006373 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006374
Peng Xu62c8c432016-05-09 15:23:02 -07006375 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006376 hdd_err("Set tx power scale failed");
6377 return -EINVAL;
6378 }
6379
6380 return 0;
6381}
6382
6383/**
6384 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6385 * @wiphy: Pointer to wireless phy
6386 * @wdev: Pointer to wireless device
6387 * @data: Pointer to data
6388 * @data_len: Data length
6389 *
6390 * Return: 0 on success, negative errno on failure
6391 */
6392static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6393 struct wireless_dev *wdev,
6394 const void *data,
6395 int data_len)
6396{
Peng Xu62c8c432016-05-09 15:23:02 -07006397 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006398
6399 cds_ssr_protect(__func__);
6400 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6401 data, data_len);
6402 cds_ssr_unprotect(__func__);
6403
6404 return ret;
6405}
6406
6407/**
6408 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6409 * @wiphy: Pointer to wireless phy
6410 * @wdev: Pointer to wireless device
6411 * @data: Pointer to data
6412 * @data_len: Data length
6413 *
6414 * Return: 0 on success, negative errno on failure
6415 */
6416static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6417 struct wireless_dev *wdev,
6418 const void *data,
6419 int data_len)
6420{
6421 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6422 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006423 hdd_adapter_t *adapter;
6424 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006425 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6426 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006427 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006428
Jeff Johnson1f61b612016-02-12 16:28:33 -08006429 ENTER_DEV(dev);
6430
Peng Xu4d67c8f2015-10-16 16:02:26 -07006431 ret = wlan_hdd_validate_context(hdd_ctx);
6432 if (ret)
6433 return ret;
6434
6435 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6436
6437 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6438 data, data_len, NULL)) {
6439 hdd_err("Invalid ATTR");
6440 return -EINVAL;
6441 }
6442
6443 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6444 hdd_err("attr tx power decrease db value failed");
6445 return -EINVAL;
6446 }
6447
6448 scale_value = nla_get_u8(tb
6449 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6450
Peng Xu62c8c432016-05-09 15:23:02 -07006451 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6452 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006453
Peng Xu62c8c432016-05-09 15:23:02 -07006454 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006455 hdd_err("Set tx power decrease db failed");
6456 return -EINVAL;
6457 }
6458
6459 return 0;
6460}
6461
6462/**
6463 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6464 * @wiphy: Pointer to wireless phy
6465 * @wdev: Pointer to wireless device
6466 * @data: Pointer to data
6467 * @data_len: Data length
6468 *
6469 * Return: 0 on success, negative errno on failure
6470 */
6471static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6472 struct wireless_dev *wdev,
6473 const void *data,
6474 int data_len)
6475{
Peng Xu62c8c432016-05-09 15:23:02 -07006476 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006477
6478 cds_ssr_protect(__func__);
6479 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6480 data, data_len);
6481 cds_ssr_unprotect(__func__);
6482
6483 return ret;
6484}
Peng Xu8fdaa492016-06-22 10:20:47 -07006485
6486/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306487 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6488 * @wiphy: Pointer to wireless phy
6489 * @wdev: Pointer to wireless device
6490 * @data: Pointer to data
6491 * @data_len: Data length
6492 *
6493 * Processes the conditional channel switch request and invokes the helper
6494 * APIs to process the channel switch request.
6495 *
6496 * Return: 0 on success, negative errno on failure
6497 */
6498static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6499 struct wireless_dev *wdev,
6500 const void *data,
6501 int data_len)
6502{
6503 int ret;
6504 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6505 struct net_device *dev = wdev->netdev;
6506 hdd_adapter_t *adapter;
6507 struct nlattr
6508 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6509 uint32_t freq_len, i;
6510 uint32_t *freq;
6511 uint8_t chans[QDF_MAX_NUM_CHAN];
6512
6513 ENTER_DEV(dev);
6514
6515 ret = wlan_hdd_validate_context(hdd_ctx);
6516 if (ret)
6517 return ret;
6518
6519 if (!hdd_ctx->config->enableDFSMasterCap) {
6520 hdd_err("DFS master capability is not present in the driver");
6521 return -EINVAL;
6522 }
6523
6524 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6525 hdd_err("Command not allowed in FTM mode");
6526 return -EPERM;
6527 }
6528
6529 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6530 if (adapter->device_mode != QDF_SAP_MODE) {
6531 hdd_err("Invalid device mode %d", adapter->device_mode);
6532 return -EINVAL;
6533 }
6534
6535 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6536 data, data_len, NULL)) {
6537 hdd_err("Invalid ATTR");
6538 return -EINVAL;
6539 }
6540
6541 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6542 hdd_err("Frequency list is missing");
6543 return -EINVAL;
6544 }
6545
6546 freq_len = nla_len(
6547 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6548 sizeof(uint32_t);
6549
6550 if (freq_len > QDF_MAX_NUM_CHAN) {
6551 hdd_err("insufficient space to hold channels");
6552 return -ENOMEM;
6553 }
6554
6555 hdd_debug("freq_len=%d", freq_len);
6556
6557 freq = nla_data(
6558 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6559
6560
6561 for (i = 0; i < freq_len; i++) {
6562 if (freq[i] == 0)
6563 chans[i] = 0;
6564 else
6565 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6566
6567 hdd_debug("freq[%d]=%d", i, freq[i]);
6568 }
6569
6570 /*
6571 * The input frequency list from user space is designed to be a
6572 * priority based frequency list. This is only to accommodate any
6573 * future request. But, current requirement is only to perform CAC
6574 * on a single channel. So, the first entry from the list is picked.
6575 *
6576 * If channel is zero, any channel in the available outdoor regulatory
6577 * domain will be selected.
6578 */
6579 ret = wlan_hdd_request_pre_cac(chans[0]);
6580 if (ret) {
6581 hdd_err("pre cac request failed with reason:%d", ret);
6582 return ret;
6583 }
6584
6585 return 0;
6586}
6587
6588/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006589 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6590 * @wiphy: Pointer to wireless phy
6591 * @wdev: Pointer to wireless device
6592 * @data: Pointer to data
6593 * @data_len: Data length
6594 *
6595 * This function is to process the p2p listen offload start vendor
6596 * command. It parses the input parameters and invoke WMA API to
6597 * send the command to firmware.
6598 *
6599 * Return: 0 on success, negative errno on failure
6600 */
6601static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6602 struct wireless_dev *wdev,
6603 const void *data,
6604 int data_len)
6605{
6606 int ret;
6607 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6608 struct net_device *dev = wdev->netdev;
6609 hdd_adapter_t *adapter;
6610 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6611 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006612
6613 ENTER_DEV(dev);
6614
6615 ret = wlan_hdd_validate_context(hdd_ctx);
6616 if (ret)
6617 return ret;
6618
6619 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6620 hdd_err("Command not allowed in FTM mode");
6621 return -EPERM;
6622 }
6623
6624 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6625 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6626 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6627 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6628 hdd_err("Invalid device mode %d", adapter->device_mode);
6629 return -EINVAL;
6630 }
6631
6632 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6633 data, data_len, NULL)) {
6634 hdd_err("Invalid ATTR");
6635 return -EINVAL;
6636 }
6637
6638 memset(&params, 0, sizeof(params));
6639
6640 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6641 params.ctl_flags = 1; /* set to default value */
6642 else
6643 params.ctl_flags = nla_get_u32(tb
6644 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6645
6646 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6647 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6648 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6649 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6650 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6651 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6652 hdd_err("Attribute parsing failed");
6653 return -EINVAL;
6654 }
6655
6656 params.vdev_id = adapter->sessionId;
6657 params.freq = nla_get_u32(tb
6658 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6659 if ((params.freq != 2412) && (params.freq != 2437) &&
6660 (params.freq != 2462)) {
6661 hdd_err("Invalid listening channel: %d", params.freq);
6662 return -EINVAL;
6663 }
6664
6665 params.period = nla_get_u32(tb
6666 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6667 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6668 hdd_err("Invalid period: %d", params.period);
6669 return -EINVAL;
6670 }
6671
6672 params.interval = nla_get_u32(tb
6673 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6674 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6675 hdd_err("Invalid interval: %d", params.interval);
6676 return -EINVAL;
6677 }
6678
6679 params.count = nla_get_u32(tb
6680 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006681 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006682 hdd_err("Invalid count: %d", params.count);
6683 return -EINVAL;
6684 }
6685
6686 params.device_types = nla_data(tb
6687 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6688 if (params.device_types == NULL) {
6689 hdd_err("Invalid device types");
6690 return -EINVAL;
6691 }
6692
6693 params.dev_types_len = nla_len(tb
6694 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6695 if (params.dev_types_len < 8) {
6696 hdd_err("Invalid device type length: %d", params.dev_types_len);
6697 return -EINVAL;
6698 }
6699
6700 params.probe_resp_tmplt = nla_data(tb
6701 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6702 if (params.probe_resp_tmplt == NULL) {
6703 hdd_err("Invalid probe response template");
6704 return -EINVAL;
6705 }
6706
6707 params.probe_resp_len = nla_len(tb
6708 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6709 if (params.probe_resp_len == 0) {
6710 hdd_err("Invalid probe resp template length: %d",
6711 params.probe_resp_len);
6712 return -EINVAL;
6713 }
6714
6715 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6716 params.freq, params.period, params.interval, params.count);
6717
Wu Gao9a704f42017-03-10 18:42:11 +08006718 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006719}
6720
6721
6722/**
6723 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6724 * @wiphy: Pointer to wireless phy
6725 * @wdev: Pointer to wireless device
6726 * @data: Pointer to data
6727 * @data_len: Data length
6728 *
6729 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6730 * to process p2p listen offload start vendor command.
6731 *
6732 * Return: 0 on success, negative errno on failure
6733 */
6734static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6735 struct wireless_dev *wdev,
6736 const void *data,
6737 int data_len)
6738{
6739 int ret = 0;
6740
6741 cds_ssr_protect(__func__);
6742 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6743 data, data_len);
6744 cds_ssr_unprotect(__func__);
6745
6746 return ret;
6747}
6748
6749/**
6750 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6751 * @wiphy: Pointer to wireless phy
6752 * @wdev: Pointer to wireless device
6753 * @data: Pointer to data
6754 * @data_len: Data length
6755 *
6756 * This function is to process the p2p listen offload stop vendor
6757 * command. It invokes WMA API to send command to firmware.
6758 *
6759 * Return: 0 on success, negative errno on failure
6760 */
6761static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6762 struct wireless_dev *wdev,
6763 const void *data,
6764 int data_len)
6765{
Peng Xu8fdaa492016-06-22 10:20:47 -07006766 hdd_adapter_t *adapter;
6767 struct net_device *dev = wdev->netdev;
6768
6769 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6770 hdd_err("Command not allowed in FTM mode");
6771 return -EPERM;
6772 }
6773
6774 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6775 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6776 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6777 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6778 hdd_err("Invalid device mode");
6779 return -EINVAL;
6780 }
6781
Wu Gao9a704f42017-03-10 18:42:11 +08006782 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006783}
6784
6785/**
6786 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6787 * @wiphy: Pointer to wireless phy
6788 * @wdev: Pointer to wireless device
6789 * @data: Pointer to data
6790 * @data_len: Data length
6791 *
6792 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6793 * to process p2p listen offload stop vendor command.
6794 *
6795 * Return: 0 on success, negative errno on failure
6796 */
6797static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6798 struct wireless_dev *wdev,
6799 const void *data,
6800 int data_len)
6801{
6802 int ret = 0;
6803
6804 cds_ssr_protect(__func__);
6805 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6806 data, data_len);
6807 cds_ssr_unprotect(__func__);
6808
6809 return ret;
6810}
6811
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306812/**
6813 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6814 * @wiphy: Pointer to wireless phy
6815 * @wdev: Pointer to wireless device
6816 * @data: Pointer to data
6817 * @data_len: Data length
6818 *
6819 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6820 * to process the conditional channel switch request.
6821 *
6822 * Return: 0 on success, negative errno on failure
6823 */
6824static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6825 struct wireless_dev *wdev,
6826 const void *data,
6827 int data_len)
6828{
6829 int ret;
6830
6831 cds_ssr_protect(__func__);
6832 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6833 data, data_len);
6834 cds_ssr_unprotect(__func__);
6835
6836 return ret;
6837}
6838
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306839/*
6840 * define short names for the global vendor params
6841 * used by __wlan_hdd_cfg80211_bpf_offload()
6842 */
6843#define BPF_INVALID \
6844 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6845#define BPF_SET_RESET \
6846 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6847#define BPF_VERSION \
6848 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6849#define BPF_FILTER_ID \
6850 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6851#define BPF_PACKET_SIZE \
6852 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6853#define BPF_CURRENT_OFFSET \
6854 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6855#define BPF_PROGRAM \
6856 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6857#define BPF_MAX \
6858 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006859
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306860static const struct nla_policy
6861wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6862 [BPF_SET_RESET] = {.type = NLA_U32},
6863 [BPF_VERSION] = {.type = NLA_U32},
6864 [BPF_FILTER_ID] = {.type = NLA_U32},
6865 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6866 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6867 [BPF_PROGRAM] = {.type = NLA_U8},
6868};
6869
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006870struct bpf_offload_priv {
6871 struct sir_bpf_get_offload bpf_get_offload;
6872};
6873
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306874/**
6875 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006876 * @context: opaque context originally passed to SME. HDD always passes
6877 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306878 * @bpf_get_offload: struct for get offload
6879 *
6880 * This function receives the response/data from the lower layer and
6881 * checks to see if the thread is still waiting then post the results to
6882 * upper layer, if the request has timed out then ignore.
6883 *
6884 * Return: None
6885 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006886static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006887 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306888{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006889 struct hdd_request *request;
6890 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306891
6892 ENTER();
6893
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006894 request = hdd_request_get(context);
6895 if (!request) {
6896 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306897 return;
6898 }
6899
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006900 priv = hdd_request_priv(request);
6901 priv->bpf_get_offload = *data;
6902 hdd_request_complete(request);
6903 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306904}
6905
6906/**
6907 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6908 * @hdd_context: hdd_context
6909 * @bpf_get_offload: struct for get offload
6910 *
6911 * Return: 0 on success, error number otherwise.
6912 */
6913static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6914 struct sir_bpf_get_offload *bpf_get_offload)
6915{
6916 struct sk_buff *skb;
6917 uint32_t nl_buf_len;
6918
6919 ENTER();
6920
6921 nl_buf_len = NLMSG_HDRLEN;
6922 nl_buf_len +=
6923 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6924 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6925
6926 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6927 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006928 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306929 return -ENOMEM;
6930 }
6931
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006932 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306933 bpf_get_offload->bpf_version,
6934 bpf_get_offload->max_bytes_for_bpf_inst);
6935
6936 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6937 bpf_get_offload->max_bytes_for_bpf_inst) ||
6938 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006939 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306940 goto nla_put_failure;
6941 }
6942
6943 cfg80211_vendor_cmd_reply(skb);
6944 EXIT();
6945 return 0;
6946
6947nla_put_failure:
6948 kfree_skb(skb);
6949 return -EINVAL;
6950}
6951
6952/**
6953 * hdd_get_bpf_offload - Get BPF offload Capabilities
6954 * @hdd_ctx: Hdd context
6955 *
6956 * Return: 0 on success, errno on failure
6957 */
6958static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6959{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306960 QDF_STATUS status;
6961 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006962 void *cookie;
6963 struct hdd_request *request;
6964 struct bpf_offload_priv *priv;
6965 static const struct hdd_request_params params = {
6966 .priv_size = sizeof(*priv),
6967 .timeout_ms = WLAN_WAIT_TIME_BPF,
6968 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306969
6970 ENTER();
6971
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006972 request = hdd_request_alloc(&params);
6973 if (!request) {
6974 hdd_err("Unable to allocate request");
6975 return -EINVAL;
6976 }
6977 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306978
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006979 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6980 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006981 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306982 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006983 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006984 ret = qdf_status_to_os_return(status);
6985 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306986 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006987 ret = hdd_request_wait_for_response(request);
6988 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006989 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006990 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306991 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006992 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306993 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006994 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306995 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006996 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306997
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006998cleanup:
6999 /*
7000 * either we never sent a request to SME, we sent a request to
7001 * SME and timed out, or we sent a request to SME, received a
7002 * response from SME, and posted the response to userspace.
7003 * regardless we are done with the request.
7004 */
7005 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307006 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007007
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307008 return ret;
7009}
7010
7011/**
7012 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7013 * @hdd_ctx: Hdd context
7014 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307015 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307016 *
7017 * Return: 0 on success; errno on failure
7018 */
7019static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7020 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307021 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307022{
7023 struct sir_bpf_set_offload *bpf_set_offload;
7024 QDF_STATUS status;
7025 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307026 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307027
7028 ENTER();
7029
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307030 if (adapter->device_mode == QDF_STA_MODE ||
7031 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7032 if (!hdd_conn_is_connected(
7033 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7034 hdd_err("Not in Connected state!");
7035 return -ENOTSUPP;
7036 }
7037 }
7038
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307039 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7040 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007041 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307042 return -ENOMEM;
7043 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307044
7045 /* Parse and fetch bpf packet size */
7046 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007047 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307048 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307049 goto fail;
7050 }
7051 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7052
7053 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007054 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307055 goto post_sme;
7056 }
7057
7058 /* Parse and fetch bpf program */
7059 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007060 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307061 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307062 goto fail;
7063 }
7064
7065 prog_len = nla_len(tb[BPF_PROGRAM]);
7066 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307067
7068 if (bpf_set_offload->program == NULL) {
7069 hdd_err("qdf_mem_malloc failed for bpf offload program");
7070 ret = -ENOMEM;
7071 goto fail;
7072 }
7073
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307074 bpf_set_offload->current_length = prog_len;
7075 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307076 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307077
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007078 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007079 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307080 bpf_set_offload->program, prog_len);
7081
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307082 /* Parse and fetch filter Id */
7083 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007084 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307085 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307086 goto fail;
7087 }
7088 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7089
7090 /* Parse and fetch current offset */
7091 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007092 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307093 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307094 goto fail;
7095 }
7096 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7097
7098post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007099 hdd_debug("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307100 bpf_set_offload->session_id,
7101 bpf_set_offload->version,
7102 bpf_set_offload->filter_id,
7103 bpf_set_offload->total_length,
7104 bpf_set_offload->current_length,
7105 bpf_set_offload->current_offset);
7106
7107 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7108 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007109 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307110 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307111 goto fail;
7112 }
7113 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307114
7115fail:
7116 if (bpf_set_offload->current_length)
7117 qdf_mem_free(bpf_set_offload->program);
7118 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307119 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307120}
7121
7122/**
7123 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7124 * @wiphy: wiphy structure pointer
7125 * @wdev: Wireless device structure pointer
7126 * @data: Pointer to the data received
7127 * @data_len: Length of @data
7128 *
7129 * Return: 0 on success; errno on failure
7130 */
7131static int
7132__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7133 struct wireless_dev *wdev,
7134 const void *data, int data_len)
7135{
7136 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7137 struct net_device *dev = wdev->netdev;
7138 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7139 struct nlattr *tb[BPF_MAX + 1];
7140 int ret_val, packet_filter_subcmd;
7141
7142 ENTER();
7143
7144 ret_val = wlan_hdd_validate_context(hdd_ctx);
7145 if (ret_val)
7146 return ret_val;
7147
7148 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007149 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307150 return -EINVAL;
7151 }
7152
7153 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007154 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307155 return -ENOTSUPP;
7156 }
7157
7158 if (nla_parse(tb, BPF_MAX, data, data_len,
7159 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007160 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307161 return -EINVAL;
7162 }
7163
7164 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007165 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307166 return -EINVAL;
7167 }
7168
7169 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7170
7171 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7172 return hdd_get_bpf_offload(hdd_ctx);
7173 else
7174 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307175 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307176}
7177
7178/**
7179 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7180 * @wiphy: wiphy structure pointer
7181 * @wdev: Wireless device structure pointer
7182 * @data: Pointer to the data received
7183 * @data_len: Length of @data
7184 *
7185 * Return: 0 on success; errno on failure
7186 */
7187
7188static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7189 struct wireless_dev *wdev,
7190 const void *data, int data_len)
7191{
7192 int ret;
7193
7194 cds_ssr_protect(__func__);
7195 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7196 cds_ssr_unprotect(__func__);
7197
7198 return ret;
7199}
7200
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307201/**
7202 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7203 * @pre_cac_adapter: AP adapter used for pre cac
7204 * @status: Status (true or false)
7205 * @handle: Global handle
7206 *
7207 * Sets the status of pre cac i.e., whether the pre cac is active or not
7208 *
7209 * Return: Zero on success, non-zero on failure
7210 */
7211static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7212 bool status, tHalHandle handle)
7213{
7214 QDF_STATUS ret;
7215
7216 ret = wlan_sap_set_pre_cac_status(
7217 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7218 if (QDF_IS_STATUS_ERROR(ret))
7219 return -EINVAL;
7220
7221 return 0;
7222}
7223
7224/**
7225 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7226 * @ap_adapter: AP adapter
7227 * @chan_before_pre_cac: Channel
7228 *
7229 * Saves the channel which the AP was beaconing on before moving to the pre
7230 * cac channel. If radar is detected on the pre cac channel, this saved
7231 * channel will be used for AP operations.
7232 *
7233 * Return: Zero on success, non-zero on failure
7234 */
7235static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7236 uint8_t chan_before_pre_cac)
7237{
7238 QDF_STATUS ret;
7239
7240 ret = wlan_sap_set_chan_before_pre_cac(
7241 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7242 if (QDF_IS_STATUS_ERROR(ret))
7243 return -EINVAL;
7244
7245 return 0;
7246}
7247
7248/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307249 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7250 * are in nol list from provided channel list
7251 * @adapter: AP adapter
7252 * @channel_count: channel count
7253 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307254 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307255 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307256 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307257static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7258 uint32_t *channel_count,
7259 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307260{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307261 uint8_t i, j;
7262 uint32_t nol_len = 0;
7263 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7264 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7265 uint32_t chan_count;
7266 bool found;
7267 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307268
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307269 if (!hdd_ctx) {
7270 hdd_err("hdd ctx not found");
7271 *channel_count = 0;
7272 return;
7273 }
7274
7275 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7276 hdd_err("invalid channel count %d", *channel_count);
7277 return;
7278 }
7279
7280 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7281 if (nol_len == 0)
7282 return;
7283
7284 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7285 chan_count = *channel_count;
7286 qdf_mem_zero(channel_list, chan_count);
7287 *channel_count = 0;
7288
7289 for (i = 0 ; i < chan_count; i++) {
7290 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7291 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7292 continue;
7293 found = false;
7294 for (j = 0; j < nol_len; j++) {
7295 if (tmp_chan_list[i] == nol[j]) {
7296 found = true;
7297 hdd_notice("skipped channel %d due to nol",
7298 nol[j]);
7299 break;
7300 }
7301 }
7302 if (!found) {
7303 channel_list[*channel_count] = tmp_chan_list[i];
7304 *channel_count = *channel_count + 1;
7305 }
7306 }
7307}
7308
7309int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7310 uint32_t *channel_count,
7311 uint8_t *channel_list)
7312{
7313 tsap_Config_t *sap_config;
7314
7315 sap_config = &adapter->sessionCtx.ap.sapConfig;
7316
7317 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7318 sap_config->acs_cfg.ch_list_count);
7319 *channel_count = sap_config->acs_cfg.ch_list_count;
7320 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7321
7322 if (*channel_count == 0) {
7323 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307324 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307325 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307326
7327 return 0;
7328}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307329
7330/**
7331 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7332 * @hdd_ctx: HDD context
7333 * @ap_adapter: AP adapter
7334 * @channel: Channel requested by userspace
7335 * @pre_cac_chan: Pointer to the pre CAC channel
7336 *
7337 * Validates the channel provided by userspace. If user provided channel 0,
7338 * a valid outdoor channel must be selected from the regulatory channel.
7339 *
7340 * Return: Zero on success and non zero value on error
7341 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007342static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7343 hdd_adapter_t *ap_adapter,
7344 uint8_t channel,
7345 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307346{
7347 uint32_t i, j;
7348 QDF_STATUS status;
7349 int ret;
7350 uint8_t nol[QDF_MAX_NUM_CHAN];
7351 uint32_t nol_len = 0, weight_len = 0;
7352 bool found;
7353 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7354 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7355 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7356
7357 if (0 == channel) {
7358 /* Channel is not obtained from PCL because PCL may not have
7359 * the entire channel list. For example: if SAP is up on
7360 * channel 6 and PCL is queried for the next SAP interface,
7361 * if SCC is preferred, the PCL will contain only the channel
7362 * 6. But, we are in need of a DFS channel. So, going with the
7363 * first channel from the valid channel list.
7364 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007365 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7366 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307367 if (QDF_IS_STATUS_ERROR(status)) {
7368 hdd_err("Failed to get channel list");
7369 return -EINVAL;
7370 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007371 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307372 pcl_weights, weight_len);
7373 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7374 for (i = 0; i < len; i++) {
7375 found = false;
7376 for (j = 0; j < nol_len; j++) {
7377 if (channel_list[i] == nol[j]) {
7378 found = true;
7379 break;
7380 }
7381 }
7382 if (found)
7383 continue;
7384 if (CDS_IS_DFS_CH(channel_list[i])) {
7385 *pre_cac_chan = channel_list[i];
7386 break;
7387 }
7388 }
7389 if (*pre_cac_chan == 0) {
7390 hdd_err("unable to find outdoor channel");
7391 return -EINVAL;
7392 }
7393 } else {
7394 /* Only when driver selects a channel, check is done for
7395 * unnsafe and NOL channels. When user provides a fixed channel
7396 * the user is expected to take care of this.
7397 */
7398 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7399 !CDS_IS_DFS_CH(channel)) {
7400 hdd_err("Invalid channel for pre cac:%d", channel);
7401 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307402 }
Jeff Johnson68755312017-02-10 11:46:55 -08007403
7404 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307405 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007406 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307407 return 0;
7408}
7409
7410/**
7411 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7412 * @channel: Channel option provided by userspace
7413 *
7414 * Sets the driver to the required hardware mode and start an adapater for
7415 * pre CAC which will mimic an AP.
7416 *
7417 * Return: Zero on success, non-zero value on error
7418 */
7419int wlan_hdd_request_pre_cac(uint8_t channel)
7420{
Krunal Sonib37bb352016-12-20 14:12:21 -08007421 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307422 hdd_context_t *hdd_ctx;
7423 int ret;
7424 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7425 hdd_ap_ctx_t *hdd_ap_ctx;
7426 QDF_STATUS status;
7427 struct wiphy *wiphy;
7428 struct net_device *dev;
7429 struct cfg80211_chan_def chandef;
7430 enum nl80211_channel_type channel_type;
7431 uint32_t freq;
7432 struct ieee80211_channel *chan;
7433 tHalHandle handle;
7434 bool val;
7435
7436 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7437 if (0 != wlan_hdd_validate_context(hdd_ctx))
7438 return -EINVAL;
7439
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007440 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307441 hdd_err("pre cac not allowed in concurrency");
7442 return -EINVAL;
7443 }
7444
7445 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7446 if (!ap_adapter) {
7447 hdd_err("unable to get SAP adapter");
7448 return -EINVAL;
7449 }
7450
7451 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7452 if (!handle) {
7453 hdd_err("Invalid handle");
7454 return -EINVAL;
7455 }
7456
7457 val = wlan_sap_is_pre_cac_active(handle);
7458 if (val) {
7459 hdd_err("pre cac is already in progress");
7460 return -EINVAL;
7461 }
7462
7463 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7464 if (!hdd_ap_ctx) {
7465 hdd_err("SAP context is NULL");
7466 return -EINVAL;
7467 }
7468
7469 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7470 hdd_err("SAP is already on DFS channel:%d",
7471 hdd_ap_ctx->operatingChannel);
7472 return -EINVAL;
7473 }
7474
7475 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7476 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7477 hdd_ap_ctx->operatingChannel);
7478 return -EINVAL;
7479 }
7480
Krunal Sonib37bb352016-12-20 14:12:21 -08007481 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7482 if (!mac_addr) {
7483 hdd_err("can't add virtual intf: Not getting valid mac addr");
7484 return -EINVAL;
7485 }
7486
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007487 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307488
7489 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7490 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007491 if (ret != 0) {
7492 hdd_err("can't validate pre-cac channel");
7493 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307494 }
7495
7496 hdd_debug("starting pre cac SAP adapter");
7497
7498 /* Starting a SAP adapter:
7499 * Instead of opening an adapter, we could just do a SME open session
7500 * for AP type. But, start BSS would still need an adapter.
7501 * So, this option is not taken.
7502 *
7503 * hdd open adapter is going to register this precac interface with
7504 * user space. This interface though exposed to user space will be in
7505 * DOWN state. Consideration was done to avoid this registration to the
7506 * user space. But, as part of SAP operations multiple events are sent
7507 * to user space. Some of these events received from unregistered
7508 * interface was causing crashes. So, retaining the registration.
7509 *
7510 * So, this interface would remain registered and will remain in DOWN
7511 * state for the CAC duration. We will add notes in the feature
7512 * announcement to not use this temporary interface for any activity
7513 * from user space.
7514 */
7515 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007516 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307517 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307518 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007519 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307520 }
7521
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307522 /*
7523 * This interface is internally created by the driver. So, no interface
7524 * up comes for this interface from user space and hence starting
7525 * the adapter internally.
7526 */
7527 if (hdd_start_adapter(pre_cac_adapter)) {
7528 hdd_err("error starting the pre cac adapter");
7529 goto close_pre_cac_adapter;
7530 }
7531
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307532 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7533
7534 wiphy = hdd_ctx->wiphy;
7535 dev = pre_cac_adapter->dev;
7536
7537 /* Since this is only a dummy interface lets us use the IEs from the
7538 * other active SAP interface. In regular scenarios, these IEs would
7539 * come from the user space entity
7540 */
7541 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7542 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7543 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7544 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307545 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307546 }
7547 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7548 ap_adapter->sessionCtx.ap.beacon,
7549 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7550 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7551 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7552 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7553 ap_adapter->sessionCtx.ap.sapConfig.authType;
7554
7555 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7556 * to operate on the same bandwidth as that of the 2.4GHz operations.
7557 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7558 */
7559 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7560 case CH_WIDTH_20MHZ:
7561 channel_type = NL80211_CHAN_HT20;
7562 break;
7563 case CH_WIDTH_40MHZ:
7564 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7565 ap_adapter->sessionCtx.ap.sapConfig.channel)
7566 channel_type = NL80211_CHAN_HT40PLUS;
7567 else
7568 channel_type = NL80211_CHAN_HT40MINUS;
7569 break;
7570 default:
7571 channel_type = NL80211_CHAN_NO_HT;
7572 break;
7573 }
7574
7575 freq = cds_chan_to_freq(pre_cac_chan);
7576 chan = __ieee80211_get_channel(wiphy, freq);
7577 if (!chan) {
7578 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307579 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307580 }
7581
7582 cfg80211_chandef_create(&chandef, chan, channel_type);
7583
7584 hdd_debug("orig width:%d channel_type:%d freq:%d",
7585 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7586 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007587 /*
7588 * Doing update after opening and starting pre-cac adapter will make
7589 * sure that driver won't do hardware mode change if there are any
7590 * initial hick-ups or issues in pre-cac adapter's configuration.
7591 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7592 * connection update should result in DBS mode
7593 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007594 status = policy_mgr_update_and_wait_for_connection_update(
7595 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007596 ap_adapter->sessionId,
7597 pre_cac_chan,
7598 SIR_UPDATE_REASON_PRE_CAC);
7599 if (QDF_IS_STATUS_ERROR(status)) {
7600 hdd_err("error in moving to DBS mode");
7601 goto stop_close_pre_cac_adapter;
7602 }
7603
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307604
7605 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7606 if (0 != ret) {
7607 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307608 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307609 }
7610
7611 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7612 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007613 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307614 if (QDF_IS_STATUS_ERROR(status)) {
7615 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307616 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307617 }
7618
7619 /*
7620 * The pre cac status is set here. But, it would not be reset explicitly
7621 * anywhere, since after the pre cac success/failure, the pre cac
7622 * adapter itself would be removed.
7623 */
7624 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7625 if (0 != ret) {
7626 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307627 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307628 }
7629
7630 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7631 hdd_ap_ctx->operatingChannel);
7632 if (0 != ret) {
7633 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307634 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307635 }
7636
7637 ap_adapter->pre_cac_chan = pre_cac_chan;
7638
7639 return 0;
7640
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307641stop_close_pre_cac_adapter:
7642 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307643 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7644 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307645close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307646 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007647release_intf_addr_and_return_failure:
7648 /*
7649 * Release the interface address as the adapter
7650 * failed to start, if you don't release then next
7651 * adapter which is trying to come wouldn't get valid
7652 * mac address. Remember we have limited pool of mac addresses
7653 */
7654 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307655 return -EINVAL;
7656}
7657
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307658static const struct nla_policy
7659wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7660 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7661};
7662
Agrawal Ashish65634612016-08-18 13:24:32 +05307663static const struct nla_policy
7664wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7665 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7666 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7667};
7668
7669/**
7670 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7671 * @wiphy: Pointer to wireless phy
7672 * @wdev: Pointer to wireless device
7673 * @data: Pointer to data
7674 * @data_len: Length of @data
7675 *
7676 * This function parses the incoming NL vendor command data attributes and
7677 * updates the SAP context about channel_hint and DFS mode.
7678 * If channel_hint is set, SAP will choose that channel
7679 * as operating channel.
7680 *
7681 * If DFS mode is enabled, driver will include DFS channels
7682 * in ACS else driver will skip DFS channels.
7683 *
7684 * Return: 0 on success, negative errno on failure
7685 */
7686static int
7687__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7688 struct wireless_dev *wdev,
7689 const void *data, int data_len)
7690{
7691 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7692 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7693 int ret;
7694 struct acs_dfs_policy *acs_policy;
7695 int mode = DFS_MODE_NONE;
7696 int channel_hint = 0;
7697
7698 ENTER_DEV(wdev->netdev);
7699
7700 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7701 hdd_err("Command not allowed in FTM mode");
7702 return -EINVAL;
7703 }
7704
7705 ret = wlan_hdd_validate_context(hdd_ctx);
7706 if (0 != ret)
7707 return ret;
7708
7709 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7710 data, data_len,
7711 wlan_hdd_set_acs_dfs_config_policy)) {
7712 hdd_err("invalid attr");
7713 return -EINVAL;
7714 }
7715
7716 acs_policy = &hdd_ctx->acs_policy;
7717 /*
7718 * SCM sends this attribute to restrict SAP from choosing
7719 * DFS channels from ACS.
7720 */
7721 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7722 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7723
7724 if (!IS_DFS_MODE_VALID(mode)) {
7725 hdd_err("attr acs dfs mode is not valid");
7726 return -EINVAL;
7727 }
7728 acs_policy->acs_dfs_mode = mode;
7729
7730 /*
7731 * SCM sends this attribute to provide an active channel,
7732 * to skip redundant ACS between drivers, and save driver start up time
7733 */
7734 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7735 channel_hint = nla_get_u8(
7736 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7737
7738 if (!IS_CHANNEL_VALID(channel_hint)) {
7739 hdd_err("acs channel is not valid");
7740 return -EINVAL;
7741 }
7742 acs_policy->acs_channel = channel_hint;
7743
7744 return 0;
7745}
7746
7747/**
7748 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7749 * @wiphy: wiphy structure pointer
7750 * @wdev: Wireless device structure pointer
7751 * @data: Pointer to the data received
7752 * @data_len: Length of @data
7753 *
7754 * This function parses the incoming NL vendor command data attributes and
7755 * updates the SAP context about channel_hint and DFS mode.
7756 *
7757 * Return: 0 on success; errno on failure
7758 */
7759static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7760 struct wireless_dev *wdev,
7761 const void *data, int data_len)
7762{
7763 int ret;
7764
7765 cds_ssr_protect(__func__);
7766 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7767 cds_ssr_unprotect(__func__);
7768
7769 return ret;
7770}
7771
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307772/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307773 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7774 * @mode : cfg80211 dfs mode
7775 *
7776 * Return: return csr sta roam dfs mode else return NONE
7777 */
7778static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7779 enum dfs_mode mode)
7780{
7781 switch (mode) {
7782 case DFS_MODE_ENABLE:
7783 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7784 break;
7785 case DFS_MODE_DISABLE:
7786 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7787 break;
7788 case DFS_MODE_DEPRIORITIZE:
7789 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7790 break;
7791 default:
7792 hdd_err("STA Roam policy dfs mode is NONE");
7793 return CSR_STA_ROAM_POLICY_NONE;
7794 }
7795}
7796
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307797/*
7798 * hdd_get_sap_operating_band: Get current operating channel
7799 * for sap.
7800 * @hdd_ctx: hdd context
7801 *
7802 * Return : Corresponding band for SAP operating channel
7803 */
7804uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7805{
7806 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7807 QDF_STATUS status;
7808 hdd_adapter_t *adapter;
7809 uint8_t operating_channel = 0;
7810 uint8_t sap_operating_band = 0;
7811 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7812 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7813 adapter = adapter_node->pAdapter;
7814
7815 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7816 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7817 &next);
7818 adapter_node = next;
7819 continue;
7820 }
7821 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7822 if (IS_24G_CH(operating_channel))
7823 sap_operating_band = eCSR_BAND_24;
7824 else if (IS_5G_CH(operating_channel))
7825 sap_operating_band = eCSR_BAND_5G;
7826 else
7827 sap_operating_band = eCSR_BAND_ALL;
7828 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7829 &next);
bings373b99b2017-01-23 10:35:08 +08007830 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307831 }
7832 return sap_operating_band;
7833}
7834
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307835static const struct nla_policy
7836wlan_hdd_set_sta_roam_config_policy[
7837QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7838 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7839 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7840};
7841
7842/**
7843 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7844 * for station connection or roaming.
7845 * @wiphy: Pointer to wireless phy
7846 * @wdev: Pointer to wireless device
7847 * @data: Pointer to data
7848 * @data_len: Length of @data
7849 *
7850 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7851 * channels needs to be skipped in scanning or not.
7852 * If dfs_mode is disabled, driver will not scan DFS channels.
7853 * If skip_unsafe_channels is set, driver will skip unsafe channels
7854 * in Scanning.
7855 *
7856 * Return: 0 on success, negative errno on failure
7857 */
7858static int
7859__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7860 struct wireless_dev *wdev,
7861 const void *data, int data_len)
7862{
7863 struct net_device *dev = wdev->netdev;
7864 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7865 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7866 struct nlattr *tb[
7867 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7868 int ret;
7869 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7870 enum dfs_mode mode = DFS_MODE_NONE;
7871 bool skip_unsafe_channels = false;
7872 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307873 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307874
7875 ENTER_DEV(dev);
7876
7877 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7878 hdd_err("Command not allowed in FTM mode");
7879 return -EINVAL;
7880 }
7881
7882 ret = wlan_hdd_validate_context(hdd_ctx);
7883 if (0 != ret)
7884 return ret;
7885 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7886 data, data_len,
7887 wlan_hdd_set_sta_roam_config_policy)) {
7888 hdd_err("invalid attr");
7889 return -EINVAL;
7890 }
7891 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7892 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7893 if (!IS_DFS_MODE_VALID(mode)) {
7894 hdd_err("attr sta roam dfs mode policy is not valid");
7895 return -EINVAL;
7896 }
7897
7898 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7899
7900 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7901 skip_unsafe_channels = nla_get_u8(
7902 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307903 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307904 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307905 skip_unsafe_channels, adapter->sessionId,
7906 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307907
7908 if (!QDF_IS_STATUS_SUCCESS(status)) {
7909 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7910 return -EINVAL;
7911 }
7912 return 0;
7913}
7914
7915/**
7916 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7917 * connection and roaming for station.
7918 * @wiphy: wiphy structure pointer
7919 * @wdev: Wireless device structure pointer
7920 * @data: Pointer to the data received
7921 * @data_len: Length of @data
7922 *
7923 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7924 * channels needs to be skipped in scanning or not.
7925 * If dfs_mode is disabled, driver will not scan DFS channels.
7926 * If skip_unsafe_channels is set, driver will skip unsafe channels
7927 * in Scanning.
7928 * Return: 0 on success; errno on failure
7929 */
7930static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7931 struct wireless_dev *wdev,
7932 const void *data, int data_len)
7933{
7934 int ret;
7935
7936 cds_ssr_protect(__func__);
7937 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7938 cds_ssr_unprotect(__func__);
7939
7940 return ret;
7941}
7942
Agrawal Ashish467dde42016-09-08 18:44:22 +05307943#ifdef FEATURE_WLAN_CH_AVOID
7944/**
7945 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7946 * is on unsafe channel.
7947 * @wiphy: wiphy structure pointer
7948 * @wdev: Wireless device structure pointer
7949 * @data: Pointer to the data received
7950 * @data_len: Length of @data
7951 *
7952 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7953 * on any of unsafe channels.
7954 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7955 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7956 *
7957 * Return: 0 on success; errno on failure
7958 */
7959static int
7960__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7961 struct wireless_dev *wdev,
7962 const void *data, int data_len)
7963{
7964 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7965 int ret;
7966 uint16_t unsafe_channel_count;
7967 int unsafe_channel_index;
7968 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7969
7970 ENTER_DEV(wdev->netdev);
7971
7972 if (!qdf_ctx) {
7973 cds_err("qdf_ctx is NULL");
7974 return -EINVAL;
7975 }
7976
7977 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7978 hdd_err("Command not allowed in FTM mode");
7979 return -EINVAL;
7980 }
7981
7982 ret = wlan_hdd_validate_context(hdd_ctx);
7983 if (0 != ret)
7984 return ret;
7985 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7986 &(hdd_ctx->unsafe_channel_count),
7987 sizeof(hdd_ctx->unsafe_channel_list));
7988
7989 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7990 (uint16_t)NUM_CHANNELS);
7991 for (unsafe_channel_index = 0;
7992 unsafe_channel_index < unsafe_channel_count;
7993 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007994 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05307995 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7996 }
7997 hdd_unsafe_channel_restart_sap(hdd_ctx);
7998 return 0;
7999}
8000
8001/**
8002 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8003 * is on unsafe channel.
8004 * @wiphy: wiphy structure pointer
8005 * @wdev: Wireless device structure pointer
8006 * @data: Pointer to the data received
8007 * @data_len: Length of @data
8008 *
8009 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8010 * on any of unsafe channels.
8011 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8012 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8013 *
8014 * Return: 0 on success; errno on failure
8015 */
8016static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8017 struct wireless_dev *wdev,
8018 const void *data, int data_len)
8019{
8020 int ret;
8021
8022 cds_ssr_protect(__func__);
8023 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8024 cds_ssr_unprotect(__func__);
8025
8026 return ret;
8027}
8028
8029#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308030/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308031 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8032 * SAP is on unsafe channel.
8033 * @wiphy: wiphy structure pointer
8034 * @wdev: Wireless device structure pointer
8035 * @data: Pointer to the data received
8036 * @data_len: Length of @data
8037 *
8038 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8039 * driver.
8040 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8041 * will initiate restart of sap.
8042 *
8043 * Return: 0 on success; errno on failure
8044 */
8045static int
8046__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8047 struct wireless_dev *wdev,
8048 const void *data, int data_len)
8049{
8050 struct net_device *ndev = wdev->netdev;
8051 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8052 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8053 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8054 uint8_t config_channel = 0;
8055 hdd_ap_ctx_t *ap_ctx;
8056 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308057 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308058
8059 ENTER();
8060
8061 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008062 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308063 return -EINVAL;
8064 }
8065
8066 ret = wlan_hdd_validate_context(hdd_ctx);
8067 if (0 != ret)
8068 return -EINVAL;
8069
8070 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8071 data, data_len,
8072 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008073 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308074 return -EINVAL;
8075 }
8076
8077 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8078 if (!test_bit(SOFTAP_BSS_STARTED,
8079 &hostapd_adapter->event_flags)) {
8080 hdd_err("SAP is not started yet. Restart sap will be invalid");
8081 return -EINVAL;
8082 }
8083
8084 config_channel =
8085 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8086
8087 if (!((IS_24G_CH(config_channel)) ||
8088 (IS_5G_CH(config_channel)))) {
8089 hdd_err("Channel %d is not valid to restart SAP",
8090 config_channel);
8091 return -ENOTSUPP;
8092 }
8093
8094 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8095 ap_ctx->sapConfig.channel = config_channel;
8096 ap_ctx->sapConfig.ch_params.ch_width =
8097 ap_ctx->sapConfig.ch_width_orig;
8098
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008099 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308100 ap_ctx->sapConfig.sec_ch,
8101 &ap_ctx->sapConfig.ch_params);
8102
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008103 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308104 }
8105
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308106 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8107 uint32_t freq_len, i;
8108 uint32_t *freq;
8109 uint8_t chans[QDF_MAX_NUM_CHAN];
8110
8111 hdd_debug("setting mandatory freq/chan list");
8112
8113 freq_len = nla_len(
8114 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8115 sizeof(uint32_t);
8116
8117 if (freq_len > QDF_MAX_NUM_CHAN) {
8118 hdd_err("insufficient space to hold channels");
8119 return -ENOMEM;
8120 }
8121
8122 freq = nla_data(
8123 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8124
8125 hdd_debug("freq_len=%d", freq_len);
8126
8127 for (i = 0; i < freq_len; i++) {
8128 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8129 hdd_debug("freq[%d]=%d", i, freq[i]);
8130 }
8131
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008132 status = policy_mgr_set_sap_mandatory_channels(
8133 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308134 if (QDF_IS_STATUS_ERROR(status))
8135 return -EINVAL;
8136 }
8137
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308138 return 0;
8139}
8140
8141/**
8142 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8143 * @wiphy: wiphy structure pointer
8144 * @wdev: Wireless device structure pointer
8145 * @data: Pointer to the data received
8146 * @data_len: Length of @data
8147 *
8148 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8149 * driver.
8150 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8151 * will initiate restart of sap.
8152 *
8153 * Return: 0 on success; errno on failure
8154 */
8155static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8156 struct wireless_dev *wdev,
8157 const void *data, int data_len)
8158{
8159 int ret;
8160
8161 cds_ssr_protect(__func__);
8162 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8163 wdev, data, data_len);
8164 cds_ssr_unprotect(__func__);
8165
8166 return ret;
8167}
8168
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308169#undef BPF_INVALID
8170#undef BPF_SET_RESET
8171#undef BPF_VERSION
8172#undef BPF_ID
8173#undef BPF_PACKET_SIZE
8174#undef BPF_CURRENT_OFFSET
8175#undef BPF_PROGRAM
8176#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308177
8178/**
8179 * define short names for the global vendor params
8180 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8181 */
8182#define PARAM_TOTAL_CMD_EVENT_WAKE \
8183 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8184#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8185 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8186#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8187 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8188#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8189 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8190#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8191 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8192#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8193 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8194#define PARAM_TOTAL_RX_DATA_WAKE \
8195 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8196#define PARAM_RX_UNICAST_CNT \
8197 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8198#define PARAM_RX_MULTICAST_CNT \
8199 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8200#define PARAM_RX_BROADCAST_CNT \
8201 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8202#define PARAM_ICMP_PKT \
8203 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8204#define PARAM_ICMP6_PKT \
8205 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8206#define PARAM_ICMP6_RA \
8207 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8208#define PARAM_ICMP6_NA \
8209 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8210#define PARAM_ICMP6_NS \
8211 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8212#define PARAM_ICMP4_RX_MULTICAST_CNT \
8213 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8214#define PARAM_ICMP6_RX_MULTICAST_CNT \
8215 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8216#define PARAM_OTHER_RX_MULTICAST_CNT \
8217 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308218#define PARAM_RSSI_BREACH_CNT \
8219 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8220#define PARAM_LOW_RSSI_CNT \
8221 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8222#define PARAM_GSCAN_CNT \
8223 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8224#define PARAM_PNO_COMPLETE_CNT \
8225 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8226#define PARAM_PNO_MATCH_CNT \
8227 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8228
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308229
8230
8231/**
8232 * hdd_send_wakelock_stats() - API to send wakelock stats
8233 * @ctx: context to be passed to callback
8234 * @data: data passed to callback
8235 *
8236 * This function is used to send wake lock stats to HAL layer
8237 *
8238 * Return: 0 on success, error number otherwise.
8239 */
8240static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8241 const struct sir_wake_lock_stats *data)
8242{
8243 struct sk_buff *skb;
8244 uint32_t nl_buf_len;
8245 uint32_t total_rx_data_wake, rx_multicast_cnt;
8246 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308247 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308248
8249 ENTER();
8250
8251 nl_buf_len = NLMSG_HDRLEN;
8252 nl_buf_len +=
8253 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8254 (NLMSG_HDRLEN + sizeof(uint32_t));
8255
8256 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8257
8258 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008259 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308260 return -ENOMEM;
8261 }
8262
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008263 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308264 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008265 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308266 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008267 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308268 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008269 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308270 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008271 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308272 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008273 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308274 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008275 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308276 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008277 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8278 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308279 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008280 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308281 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008282 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308283 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008284 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308285 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008286 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308287 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008288 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308289 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308290
8291 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308292 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308293
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308294 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308295 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308296
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308297 rx_multicast_cnt =
8298 data->wow_ipv4_mcast_wake_up_count +
8299 ipv6_rx_multicast_addr_cnt;
8300
8301 total_rx_data_wake =
8302 data->wow_ucast_wake_up_count +
8303 data->wow_bcast_wake_up_count +
8304 rx_multicast_cnt;
8305
8306 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8307 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8308 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8309 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8310 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8311 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8312 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8313 total_rx_data_wake) ||
8314 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8315 data->wow_ucast_wake_up_count) ||
8316 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8317 rx_multicast_cnt) ||
8318 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8319 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308320 nla_put_u32(skb, PARAM_ICMP_PKT,
8321 data->wow_icmpv4_count) ||
8322 nla_put_u32(skb, PARAM_ICMP6_PKT,
8323 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308324 nla_put_u32(skb, PARAM_ICMP6_RA,
8325 data->wow_ipv6_mcast_ra_stats) ||
8326 nla_put_u32(skb, PARAM_ICMP6_NA,
8327 data->wow_ipv6_mcast_na_stats) ||
8328 nla_put_u32(skb, PARAM_ICMP6_NS,
8329 data->wow_ipv6_mcast_ns_stats) ||
8330 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8331 data->wow_ipv4_mcast_wake_up_count) ||
8332 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8333 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308334 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8335 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8336 data->wow_rssi_breach_wake_up_count) ||
8337 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8338 data->wow_low_rssi_wake_up_count) ||
8339 nla_put_u32(skb, PARAM_GSCAN_CNT,
8340 data->wow_gscan_wake_up_count) ||
8341 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8342 data->wow_pno_complete_wake_up_count) ||
8343 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8344 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008345 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308346 goto nla_put_failure;
8347 }
8348
8349 cfg80211_vendor_cmd_reply(skb);
8350
8351 EXIT();
8352 return 0;
8353
8354nla_put_failure:
8355 kfree_skb(skb);
8356 return -EINVAL;
8357}
8358
8359/**
8360 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8361 * @wiphy: wiphy pointer
8362 * @wdev: pointer to struct wireless_dev
8363 * @data: pointer to incoming NL vendor data
8364 * @data_len: length of @data
8365 *
8366 * This function parses the incoming NL vendor command data attributes and
8367 * invokes the SME Api and blocks on a completion variable.
8368 * WMA copies required data and invokes callback
8369 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8370 *
8371 * Return: 0 on success; error number otherwise.
8372 */
8373static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8374 struct wireless_dev *wdev,
8375 const void *data,
8376 int data_len)
8377{
8378 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8379 int status, ret;
8380 struct sir_wake_lock_stats wake_lock_stats;
8381 QDF_STATUS qdf_status;
8382
8383 ENTER();
8384
8385 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008386 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308387 return -EINVAL;
8388 }
8389
8390 status = wlan_hdd_validate_context(hdd_ctx);
8391 if (0 != status)
8392 return -EINVAL;
8393
8394 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8395 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008396 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308397 return -EINVAL;
8398 }
8399
8400 ret = hdd_send_wakelock_stats(hdd_ctx,
8401 &wake_lock_stats);
8402 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008403 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308404
8405 EXIT();
8406 return ret;
8407}
8408
8409/**
8410 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8411 * @wiphy: wiphy pointer
8412 * @wdev: pointer to struct wireless_dev
8413 * @data: pointer to incoming NL vendor data
8414 * @data_len: length of @data
8415 *
8416 * This function parses the incoming NL vendor command data attributes and
8417 * invokes the SME Api and blocks on a completion variable.
8418 * WMA copies required data and invokes callback
8419 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8420 *
8421 * Return: 0 on success; error number otherwise.
8422 */
8423static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8424 struct wireless_dev *wdev,
8425 const void *data, int data_len)
8426{
8427 int ret;
8428
8429 cds_ssr_protect(__func__);
8430 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8431 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008432 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308433
8434 return ret;
8435}
8436
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308437/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308438 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8439 * @wiphy: wiphy structure pointer
8440 * @wdev: Wireless device structure pointer
8441 * @data: Pointer to the data received
8442 * @data_len: Length of @data
8443 *
8444 * This function reads wmi max bus size and fill in the skb with
8445 * NL attributes and send up the NL event.
8446 * Return: 0 on success; errno on failure
8447 */
8448static int
8449__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8450 struct wireless_dev *wdev,
8451 const void *data, int data_len)
8452{
8453 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8454 int ret_val;
8455 struct sk_buff *skb;
8456 uint32_t nl_buf_len;
8457
8458 ENTER();
8459
8460 ret_val = wlan_hdd_validate_context(hdd_ctx);
8461 if (ret_val)
8462 return ret_val;
8463
8464 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8465 hdd_err("Command not allowed in FTM mode");
8466 return -EINVAL;
8467 }
8468
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008469 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308470
8471 nl_buf_len = NLMSG_HDRLEN;
8472 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8473
8474 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8475 if (!skb) {
8476 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8477 return -ENOMEM;
8478 }
8479
8480 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8481 hdd_ctx->wmi_max_len)) {
8482 hdd_err("nla put failure");
8483 goto nla_put_failure;
8484 }
8485
8486 cfg80211_vendor_cmd_reply(skb);
8487
8488 EXIT();
8489
8490 return 0;
8491
8492nla_put_failure:
8493 kfree_skb(skb);
8494 return -EINVAL;
8495}
8496
8497/**
8498 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8499 * @wiphy: wiphy structure pointer
8500 * @wdev: Wireless device structure pointer
8501 * @data: Pointer to the data received
8502 * @data_len: Length of @data
8503 *
8504 * Return: 0 on success; errno on failure
8505 */
8506static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8507 struct wireless_dev *wdev,
8508 const void *data, int data_len)
8509{
8510 int ret;
8511
8512 cds_ssr_protect(__func__);
8513 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8514 cds_ssr_unprotect(__func__);
8515
8516 return ret;
8517}
8518
8519/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308520 *__wlan_hdd_cfg80211_setband() - set band
8521 * @wiphy: Pointer to wireless phy
8522 * @wdev: Pointer to wireless device
8523 * @data: Pointer to data
8524 * @data_len: Length of @data
8525 *
8526 * Return: 0 on success, negative errno on failure
8527 */
8528static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8529 struct wireless_dev *wdev,
8530 const void *data, int data_len)
8531{
8532 struct net_device *dev = wdev->netdev;
8533 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8534 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8535 int ret;
8536 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8537 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8538
8539 ENTER();
8540
8541 ret = wlan_hdd_validate_context(hdd_ctx);
8542 if (ret)
8543 return ret;
8544
8545 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8546 hdd_err(FL("Invalid ATTR"));
8547 return -EINVAL;
8548 }
8549
8550 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8551 hdd_err(FL("attr SETBAND_VALUE failed"));
8552 return -EINVAL;
8553 }
8554
8555 ret = hdd_set_band(dev,
8556 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8557
8558 EXIT();
8559 return ret;
8560}
8561
8562/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308563 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8564 * @adapter: hdd adapter
8565 * @channel: channel number
8566 *
8567 * return: QDF status based on success or failure
8568 */
8569static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8570 int channel, int chan_bw)
8571{
8572 if (QDF_STATUS_SUCCESS !=
8573 wlan_hdd_validate_operation_channel(adapter, channel))
8574 return QDF_STATUS_E_FAILURE;
8575 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8576 channel,
8577 PHY_SINGLE_CHANNEL_CENTERED))) {
8578 hdd_notice("channel %d is in nol", channel);
8579 return -EINVAL;
8580 }
8581
8582 if ((wlansap_is_channel_leaking_in_nol(
8583 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8584 channel, chan_bw))) {
8585 hdd_notice("channel %d is leaking in nol", channel);
8586 return -EINVAL;
8587 }
8588
8589 return 0;
8590
8591}
8592
Kapil Gupta8878ad92017-02-13 11:56:04 +05308593static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8594 tsap_Config_t *sap_config,
8595 struct hdd_vendor_chan_info *channel_list)
8596{
8597 sap_config->channel = channel_list->pri_ch;
8598
8599 sap_config->ch_params.center_freq_seg0 =
8600 channel_list->vht_seg0_center_ch;
8601 sap_config->ch_params.center_freq_seg1 =
8602 channel_list->vht_seg1_center_ch;
8603
8604 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8605 sap_config->ch_params.ch_width = channel_list->chan_width;
8606 if (sap_config->channel >= 36)
8607 sap_config->ch_width_orig =
8608 hdd_ctx->config->vhtChannelWidth;
8609 else
8610 sap_config->ch_width_orig =
8611 hdd_ctx->config->nChannelBondingMode24GHz ?
8612 eHT_CHANNEL_WIDTH_40MHZ :
8613 eHT_CHANNEL_WIDTH_20MHZ;
8614
8615 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8616 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8617 sap_config->acs_cfg.vht_seg0_center_ch =
8618 channel_list->vht_seg0_center_ch;
8619 sap_config->acs_cfg.vht_seg1_center_ch =
8620 channel_list->vht_seg1_center_ch;
8621 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8622}
8623
8624static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8625 uint8_t channel_cnt,
8626 struct hdd_vendor_chan_info *channel_list)
8627{
8628 tsap_Config_t *sap_config;
8629 hdd_ap_ctx_t *hdd_ap_ctx;
8630 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8631 QDF_STATUS status = QDF_STATUS_SUCCESS;
8632
8633 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8634 sap_config = &adapter->sessionCtx.ap.sapConfig;
8635
8636 if (QDF_TIMER_STATE_RUNNING ==
8637 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8638 ap.vendor_acs_timer)) {
8639 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8640 }
8641
8642 if (channel_list && channel_list->pri_ch == 0) {
8643 /* Check mode, set default channel */
8644 channel_list->pri_ch = 6;
8645 /*
8646 * sap_select_default_oper_chan(hdd_ctx->hHal,
8647 * sap_config->acs_cfg.hw_mode);
8648 */
8649 }
8650
8651 switch (reason) {
8652 /* SAP init case */
8653 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8654 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8655 /* Update Hostapd */
8656 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8657 break;
8658
8659 /* DFS detected on current channel */
8660 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8661 wlan_sap_update_next_channel(
8662 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8663 channel_list->pri_ch,
8664 channel_list->chan_width);
8665 status = sme_update_new_channel_event(
8666 WLAN_HDD_GET_HAL_CTX(adapter),
8667 adapter->sessionId);
8668 break;
8669
8670 /* LTE coex event on current channel */
8671 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8672 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8673 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8674 hdd_ap_ctx->sapConfig.ch_width_orig =
8675 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008676 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308677 break;
8678
8679 default:
8680 hdd_info("invalid reason for timer invoke");
8681 }
8682 qdf_mem_free(channel_list);
8683 EXIT();
8684 return status;
8685}
8686
8687/**
8688 * Define short name for vendor channel set config
8689 */
8690#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8691#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8692#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8693#define SET_CHAN_PRIMARY_CHANNEL \
8694 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8695#define SET_CHAN_SECONDARY_CHANNEL \
8696 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8697#define SET_CHAN_SEG0_CENTER_CHANNEL \
8698 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8699#define SET_CHAN_SEG1_CENTER_CHANNEL \
8700 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8701#define SET_CHAN_CHANNEL_WIDTH \
8702 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8703#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8704
8705/**
8706 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8707 * @channel_list: pointer to hdd_vendor_chan_info
8708 * @reason: channel change reason
8709 * @channel_cnt: channel count
8710 * @data: data
8711 * @data_len: data len
8712 *
8713 * Return: 0 on success, negative errno on failure
8714 */
8715static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8716 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8717 const void *data, int data_len)
8718{
8719 int rem, i = 0;
8720 struct nlattr *tb[SET_CHAN_MAX + 1];
8721 struct nlattr *tb2[SET_CHAN_MAX + 1];
8722 struct nlattr *curr_attr;
8723 struct hdd_vendor_chan_info *channel_list;
8724
8725 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8726 hdd_err("Invalid ATTR");
8727 return -EINVAL;
8728 }
8729
8730 if (tb[SET_CHAN_REASON])
8731 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8732
8733 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8734 *channel_cnt = nla_get_u8(tb[
8735 SET_CHAN_CHANNEL_COUNT]);
8736 hdd_info("channel count %d", *channel_cnt);
8737 }
8738
8739 if (!(*channel_cnt)) {
8740 hdd_err("channel count is %d", *channel_cnt);
8741 return -EINVAL;
8742 }
8743
8744 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8745 (*channel_cnt));
8746
8747 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8748 if (nla_parse(tb2,
8749 SET_CHAN_MAX,
8750 nla_data(curr_attr), nla_len(curr_attr),
8751 NULL)) {
8752 hdd_err("nla_parse failed");
8753 return -EINVAL;
8754 }
8755 /* Parse and Fetch allowed SSID list*/
8756 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8757 channel_list[i].pri_ch =
8758 nla_get_u8(
8759 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8760 }
8761 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8762 channel_list[i].ht_sec_ch =
8763 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8764 }
8765 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8766 channel_list[i].vht_seg0_center_ch =
8767 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8768 }
8769 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8770 channel_list[i].vht_seg1_center_ch =
8771 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8772 }
8773 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8774 channel_list[i].chan_width =
8775 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8776 }
8777 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8778 i, channel_list[i].pri_ch,
8779 channel_list[i].ht_sec_ch,
8780 channel_list[i].vht_seg0_center_ch,
8781 channel_list[i].vht_seg1_center_ch,
8782 channel_list[i].chan_width);
8783 i++;
8784 if (i > *channel_cnt)
8785 break;
8786 }
8787 *chan_list_ptr = channel_list;
8788
8789 return 0;
8790}
8791
8792/**
8793 * Undef short names for vendor set channel configuration
8794 */
8795#undef SET_CHAN_REASON
8796#undef SET_CHAN_CHANNEL_COUNT
8797#undef SET_CHAN_CHAN_LIST
8798#undef SET_CHAN_PRIMARY_CHANNEL
8799#undef SET_CHAN_SECONDARY_CHANNEL
8800#undef SET_CHAN_SEG0_CENTER_CHANNEL
8801#undef SET_CHAN_SEG1_CENTER_CHANNEL
8802#undef SET_CHAN_CHANNEL_WIDTH
8803#undef SET_CHAN_MAX
8804
8805/**
8806 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8807 * @wiphy: Pointer to wireless phy
8808 * @wdev: Pointer to wireless device
8809 * @data: Pointer to data
8810 * @data_len: Length of @data
8811 *
8812 * Return: 0 on success, negative errno on failure
8813 */
8814static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8815 struct wireless_dev *wdev,
8816 const void *data, int data_len)
8817{
8818 int ret_val;
8819 QDF_STATUS qdf_status;
8820 uint8_t channel_cnt = 0, reason = -1;
8821 struct hdd_vendor_chan_info *channel_list = NULL;
8822 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8823 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8824
8825 ENTER();
8826
8827 ret_val = wlan_hdd_validate_context(hdd_ctx);
8828 if (ret_val)
8829 return ret_val;
8830
8831 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8832 hdd_err("Command not allowed in FTM mode");
8833 return -EINVAL;
8834 }
8835
8836 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8837 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8838 else {
8839 hdd_err("already timeout happened for acs");
8840 return -EINVAL;
8841 }
8842
8843 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8844 &channel_cnt, data, data_len);
8845 if (ret_val)
8846 return ret_val;
8847
8848 /* Validate channel to be set */
8849 while (channel_cnt && channel_list) {
8850 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8851 channel_list->pri_ch,
8852 channel_list->chan_width);
8853 if (qdf_status == QDF_STATUS_SUCCESS)
8854 break;
8855 channel_cnt--;
8856 channel_list++;
8857 }
8858 if ((channel_cnt <= 0) || !channel_list) {
8859 hdd_err("no available channel/chanlist %p", channel_list);
8860 return -EINVAL;
8861 }
8862
8863 qdf_status = hdd_update_acs_channel(adapter, reason,
8864 channel_cnt, channel_list);
8865 return qdf_status_to_os_return(qdf_status);
8866}
8867
8868/**
8869 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8870 * @wiphy: Pointer to wireless phy
8871 * @wdev: Pointer to wireless device
8872 * @data: Pointer to data
8873 * @data_len: Length of @data
8874 *
8875 * Return: 0 on success, negative errno on failure
8876 */
8877static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8878 struct wireless_dev *wdev,
8879 const void *data, int data_len)
8880{
8881 int ret;
8882
8883 cds_ssr_protect(__func__);
8884 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8885 data_len);
8886 cds_ssr_protect(__func__);
8887
8888 return ret;
8889}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308890
8891/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308892 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8893 * @wiphy: wiphy structure pointer
8894 * @wdev: Wireless device structure pointer
8895 * @data: Pointer to the data received
8896 * @data_len: Length of @data
8897 *
8898 * Return: 0 on success; errno on failure
8899 */
8900static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8901 struct wireless_dev *wdev,
8902 const void *data, int data_len)
8903{
8904 int ret;
8905
8906 cds_ssr_protect(__func__);
8907 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8908 cds_ssr_unprotect(__func__);
8909
8910 return ret;
8911}
8912
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008913/**
8914 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8915 * @nl80211_value: Vendor command attribute value
8916 * @wmi_value: Pointer to return converted WMI return value
8917 *
8918 * Convert NL80211 vendor command value for SAR limit set to WMI value
8919 * Return: 0 on success, -1 on invalid value
8920 */
8921static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8922 u32 *wmi_value)
8923{
8924 int ret = 0;
8925
8926 switch (nl80211_value) {
8927 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8928 *wmi_value = WMI_SAR_FEATURE_OFF;
8929 break;
8930 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8931 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8932 break;
8933 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8934 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8935 break;
8936 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8937 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8938 break;
8939 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8940 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8941 break;
8942 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8943 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8944 break;
8945 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8946 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8947 break;
8948 default:
8949 ret = -1;
8950 }
8951 return ret;
8952}
8953
8954/**
8955 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8956 * @nl80211_value: Vendor command attribute value
8957 * @wmi_value: Pointer to return converted WMI return value
8958 *
8959 * Convert NL80211 vendor command value for SAR BAND to WMI value
8960 * Return: 0 on success, -1 on invalid value
8961 */
8962static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8963{
8964 int ret = 0;
8965
8966 switch (nl80211_value) {
8967 case NL80211_BAND_2GHZ:
8968 *wmi_value = WMI_SAR_2G_ID;
8969 break;
8970 case NL80211_BAND_5GHZ:
8971 *wmi_value = WMI_SAR_5G_ID;
8972 break;
8973 default:
8974 ret = -1;
8975 }
8976 return ret;
8977}
8978
8979/**
8980 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8981 * @nl80211_value: Vendor command attribute value
8982 * @wmi_value: Pointer to return converted WMI return value
8983 *
8984 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8985 * Return: 0 on success, -1 on invalid value
8986 */
8987static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8988 u32 *wmi_value)
8989{
8990 int ret = 0;
8991
8992 switch (nl80211_value) {
8993 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8994 *wmi_value = WMI_SAR_MOD_CCK;
8995 break;
8996 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8997 *wmi_value = WMI_SAR_MOD_OFDM;
8998 break;
8999 default:
9000 ret = -1;
9001 }
9002 return ret;
9003}
9004
9005
9006/**
9007 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9008 * @wiphy: Pointer to wireless phy
9009 * @wdev: Pointer to wireless device
9010 * @data: Pointer to data
9011 * @data_len: Length of @data
9012 *
9013 * This function is used to setup Specific Absorption Rate limit specs.
9014 *
9015 * Return: 0 on success, negative errno on failure
9016 */
9017static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9018 struct wireless_dev *wdev,
9019 const void *data, int data_len)
9020{
9021 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9022 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9023 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9024 *sar_spec_list;
9025 struct sar_limit_cmd_params sar_limit_cmd = {0};
9026 int ret = -EINVAL, i = 0, rem = 0;
9027
9028 ENTER();
9029
9030 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9031 hdd_err("Command not allowed in FTM mode");
9032 return -EPERM;
9033 }
9034
9035 if (wlan_hdd_validate_context(hdd_ctx))
9036 return -EINVAL;
9037
9038 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9039 data, data_len, NULL)) {
9040 hdd_err("Invalid SAR attributes");
9041 return -EINVAL;
9042 }
9043
9044 /* Vendor command manadates all SAR Specs in single call */
9045 sar_limit_cmd.commit_limits = 1;
9046 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9047 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9048 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9049 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9050 &sar_limit_cmd.sar_enable) < 0) {
9051 hdd_err("Invalid SAR Enable attr");
9052 goto fail;
9053 }
9054 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009055 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009056
9057 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9058 sar_limit_cmd.num_limit_rows = nla_get_u32(
9059 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009060 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009061 sar_limit_cmd.num_limit_rows);
9062 }
9063 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9064 hdd_err("SAR Spec list exceed supported size");
9065 goto fail;
9066 }
9067 if (sar_limit_cmd.num_limit_rows == 0)
9068 goto send_sar_limits;
9069 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9070 struct sar_limit_cmd_row) *
9071 sar_limit_cmd.num_limit_rows);
9072 if (!sar_limit_cmd.sar_limit_row_list) {
9073 ret = -ENOMEM;
9074 goto fail;
9075 }
9076 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9077 hdd_err("Invalid SAR SPECs list");
9078 goto fail;
9079 }
9080
9081 nla_for_each_nested(sar_spec_list,
9082 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9083 if (i == sar_limit_cmd.num_limit_rows) {
9084 hdd_warn("SAR Cmd has excess SPECs in list");
9085 break;
9086 }
9087
9088 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9089 nla_data(sar_spec_list), nla_len(sar_spec_list),
9090 NULL)) {
9091 hdd_err("nla_parse failed for SAR Spec list");
9092 goto fail;
9093 }
9094 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9095 if (sar_spec[
9096 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9097 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9098 nla_get_u32(sar_spec[
9099 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9100 } else {
9101 hdd_err("SAR Spec does not have power limit value");
9102 goto fail;
9103 }
9104
9105 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9106 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9107 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9108 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9109 < 0) {
9110 hdd_err("Invalid SAR Band attr");
9111 goto fail;
9112 }
9113 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9114 WMI_SAR_BAND_ID_VALID_MASK;
9115 }
9116 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9117 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9118 nla_get_u32(sar_spec[
9119 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9120 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9121 WMI_SAR_CHAIN_ID_VALID_MASK;
9122 }
9123 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9124 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9125 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9126 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9127 < 0) {
9128 hdd_err("Invalid SAR Modulation attr");
9129 goto fail;
9130 }
9131 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9132 WMI_SAR_MOD_ID_VALID_MASK;
9133 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009134 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009135 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9136 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9137 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9138 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9139 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9140 i++;
9141 }
9142
9143 if (i < sar_limit_cmd.num_limit_rows) {
9144 hdd_warn("SAR Cmd has less SPECs in list");
9145 sar_limit_cmd.num_limit_rows = i;
9146 }
9147
9148send_sar_limits:
9149 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9150 QDF_STATUS_SUCCESS)
9151 ret = 0;
9152fail:
9153 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9154 return ret;
9155}
9156
9157/**
9158 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9159 * @wiphy: Pointer to wireless phy
9160 * @wdev: Pointer to wireless device
9161 * @data: Pointer to data
9162 * @data_len: Length of @data
9163 *
9164 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9165 *
9166 * Return: 0 on success, negative errno on failure
9167 */
9168static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9169 struct wireless_dev *wdev,
9170 const void *data,
9171 int data_len)
9172{
9173 int ret;
9174
9175 cds_ssr_protect(__func__);
9176 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9177 data_len);
9178 cds_ssr_unprotect(__func__);
9179
9180 return ret;
9181}
9182
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309183static const struct
9184nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9185 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9186 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9187 .len = QDF_MAC_ADDR_SIZE},
9188};
9189
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309190void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9191{
9192 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9193 hdd_adapter_t *adapter;
9194
9195 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9196 if (!adapter) {
9197 hdd_err("adapter NULL");
9198 return;
9199 }
9200
9201 adapter->lfr_fw_status.is_disabled = rso_status->status;
9202 complete(&adapter->lfr_fw_status.disable_lfr_event);
9203}
9204
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309205/**
9206 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9207 * @wiphy: Pointer to wireless phy
9208 * @wdev: Pointer to wireless device
9209 * @data: Pointer to data
9210 * @data_len: Length of @data
9211 *
9212 * This function is used to enable/disable roaming using vendor commands
9213 *
9214 * Return: 0 on success, negative errno on failure
9215 */
9216static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9217 struct wireless_dev *wdev,
9218 const void *data, int data_len)
9219{
9220 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9221 struct net_device *dev = wdev->netdev;
9222 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9223 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309224 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309225 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309226 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309227 unsigned long rc;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309228
9229 ENTER_DEV(dev);
9230
9231 ret = wlan_hdd_validate_context(hdd_ctx);
9232 if (0 != ret)
9233 return ret;
9234
9235 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9236 hdd_err("Command not allowed in FTM mode");
9237 return -EINVAL;
9238 }
9239
9240 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9241 qca_wlan_vendor_attr);
9242 if (ret) {
9243 hdd_err("Invalid ATTR");
9244 return -EINVAL;
9245 }
9246
9247 /* Parse and fetch Enable flag */
9248 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9249 hdd_err("attr enable failed");
9250 return -EINVAL;
9251 }
9252
9253 is_fast_roam_enabled = nla_get_u32(
9254 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009255 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009256 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309257
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009258 if (!adapter->fast_roaming_allowed) {
9259 hdd_err("fast roaming not allowed on %s interface",
9260 adapter->dev->name);
9261 return -EINVAL;
9262 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309263 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309264 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309265 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309266 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309267 if (qdf_status != QDF_STATUS_SUCCESS)
9268 hdd_err("sme_config_fast_roaming failed with status=%d",
9269 qdf_status);
9270 ret = qdf_status_to_os_return(qdf_status);
9271
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309272 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
9273 if (QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9274 /*
9275 * wait only for LFR disable in fw as LFR enable
9276 * is always success
9277 */
9278 rc = wait_for_completion_timeout(
9279 &adapter->lfr_fw_status.disable_lfr_event,
9280 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9281 if (!rc) {
9282 hdd_err("Timed out waiting for RSO CMD status");
9283 return -ETIMEDOUT;
9284 }
9285
9286 if (!adapter->lfr_fw_status.is_disabled) {
9287 hdd_err("Roam disable attempt in FW fails");
9288 return -EBUSY;
9289 }
9290 }
9291
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309292 EXIT();
9293 return ret;
9294}
9295
9296/**
9297 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9298 * @wiphy: Pointer to wireless phy
9299 * @wdev: Pointer to wireless device
9300 * @data: Pointer to data
9301 * @data_len: Length of @data
9302 *
9303 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9304 *
9305 * Return: 0 on success, negative errno on failure
9306 */
9307static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9308 struct wireless_dev *wdev,
9309 const void *data, int data_len)
9310{
9311 int ret;
9312
9313 cds_ssr_protect(__func__);
9314 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9315 cds_ssr_unprotect(__func__);
9316
9317 return ret;
9318}
9319
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309320static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9321 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9322 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9323 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9324 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9325};
9326
9327/**
9328 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9329 * @wiphy: Pointer to wireless phy
9330 * @wdev: Pointer to wireless device
9331 * @data: Pointer to data
9332 * @data_len: Length of @data
9333 *
9334 * Return: 0 on success, negative errno on failure
9335 */
9336static int
9337__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9338 struct wireless_dev *wdev,
9339 const void *data,
9340 int data_len)
9341{
9342 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9343 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9344 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9345 struct nlattr *apth;
9346 int rem;
9347 int ret = 1;
9348 int print_idx = -1;
9349 int module_id = -1;
9350 int bit_mask = -1;
9351 int status;
9352
9353 ENTER();
9354
9355 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9356 hdd_err("Command not allowed in FTM mode");
9357 return -EINVAL;
9358 }
9359
9360 ret = wlan_hdd_validate_context(hdd_ctx);
9361 if (ret != 0)
9362 return -EINVAL;
9363
9364 print_idx = qdf_get_pidx();
9365 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9366 hdd_err("Invalid print controle object index");
9367 return -EINVAL;
9368 }
9369
9370 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9371 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9372 hdd_err("Invalid attr");
9373 return -EINVAL;
9374 }
9375
9376 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9377 hdd_err("attr trace level param failed");
9378 return -EINVAL;
9379 }
9380
9381 nla_for_each_nested(apth,
9382 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9383 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9384 nla_data(apth), nla_len(apth), NULL)) {
9385 hdd_err("Invalid attr");
9386 return -EINVAL;
9387 }
9388
9389 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9390 hdd_err("attr Module ID failed");
9391 return -EINVAL;
9392 }
9393 module_id = nla_get_u32
9394 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9395
9396 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9397 hdd_err("attr Verbose mask failed");
9398 return -EINVAL;
9399 }
9400 bit_mask = nla_get_u32
9401 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9402
9403 status = hdd_qdf_trace_enable(module_id, bit_mask);
9404
9405 if (status != 0)
9406 hdd_err("can not set verbose mask %d for the category %d",
9407 bit_mask, module_id);
9408 }
9409
9410 EXIT();
9411 return ret;
9412}
9413
9414/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309415 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9416 * @wiphy: Pointer to wireless phy
9417 * @wdev: Pointer to wireless device
9418 * @data: Pointer to data
9419 * @data_len: Length of @data
9420 *
9421 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9422 *
9423 * Return: 0 on success, negative errno on failure
9424 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309425
9426static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9427 struct wireless_dev *wdev,
9428 const void *data,
9429 int data_len)
9430{
9431 int ret;
9432
9433 cds_ssr_protect(__func__);
9434 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9435 cds_ssr_unprotect(__func__);
9436
9437 return ret;
9438}
9439
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009440const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9441 {
9442 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9443 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9444 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309445 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009446 .doit = is_driver_dfs_capable
9447 },
9448
9449#ifdef WLAN_FEATURE_NAN
9450 {
9451 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9452 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9453 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9454 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9455 .doit = wlan_hdd_cfg80211_nan_request
9456 },
9457#endif
9458
9459#ifdef WLAN_FEATURE_STATS_EXT
9460 {
9461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9464 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9465 .doit = wlan_hdd_cfg80211_stats_ext_request
9466 },
9467#endif
9468#ifdef FEATURE_WLAN_EXTSCAN
9469 {
9470 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9471 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9472 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9473 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9474 .doit = wlan_hdd_cfg80211_extscan_start
9475 },
9476 {
9477 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9478 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9479 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9480 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9481 .doit = wlan_hdd_cfg80211_extscan_stop
9482 },
9483 {
9484 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9485 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9486 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9487 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9488 },
9489 {
9490 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9491 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9492 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9493 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9494 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9495 },
9496 {
9497 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9498 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9499 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9500 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9501 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9502 },
9503 {
9504 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9505 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9506 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9507 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9508 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9509 },
9510 {
9511 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9512 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9513 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9514 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9515 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9516 },
9517 {
9518 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9519 .info.subcmd =
9520 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9521 .flags =
9522 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9523 WIPHY_VENDOR_CMD_NEED_RUNNING,
9524 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9525 },
9526 {
9527 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9528 .info.subcmd =
9529 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9530 .flags =
9531 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9532 WIPHY_VENDOR_CMD_NEED_RUNNING,
9533 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9534 },
9535 {
9536 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9537 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9538 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9539 WIPHY_VENDOR_CMD_NEED_NETDEV |
9540 WIPHY_VENDOR_CMD_NEED_RUNNING,
9541 .doit = wlan_hdd_cfg80211_set_epno_list
9542 },
9543#endif /* FEATURE_WLAN_EXTSCAN */
9544
9545#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9546 {
9547 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9548 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9549 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9550 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9551 .doit = wlan_hdd_cfg80211_ll_stats_clear
9552 },
9553
9554 {
9555 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9556 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9557 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9558 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9559 .doit = wlan_hdd_cfg80211_ll_stats_set
9560 },
9561
9562 {
9563 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9564 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9565 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9566 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9567 .doit = wlan_hdd_cfg80211_ll_stats_get
9568 },
9569#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9570#ifdef FEATURE_WLAN_TDLS
9571 {
9572 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9573 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9574 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9575 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9576 .doit = wlan_hdd_cfg80211_exttdls_enable
9577 },
9578 {
9579 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9580 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9581 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9582 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9583 .doit = wlan_hdd_cfg80211_exttdls_disable
9584 },
9585 {
9586 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9587 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9588 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9589 .doit = wlan_hdd_cfg80211_exttdls_get_status
9590 },
9591#endif
9592 {
9593 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9594 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9595 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9596 .doit = wlan_hdd_cfg80211_get_supported_features
9597 },
9598 {
9599 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9600 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9601 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9602 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9603 },
9604 {
9605 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9606 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9607 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309608 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009609 },
9610 {
9611 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9612 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9613 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9614 WIPHY_VENDOR_CMD_NEED_NETDEV,
9615 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9616 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009617 {
9618 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9619 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9620 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9621 WIPHY_VENDOR_CMD_NEED_NETDEV,
9622 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9623 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009624 {
9625 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309626 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9627 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9628 WIPHY_VENDOR_CMD_NEED_NETDEV |
9629 WIPHY_VENDOR_CMD_NEED_RUNNING,
9630 .doit = hdd_cfg80211_get_station_cmd
9631 },
9632 {
9633 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009634 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9635 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9636 WIPHY_VENDOR_CMD_NEED_NETDEV |
9637 WIPHY_VENDOR_CMD_NEED_RUNNING,
9638 .doit = wlan_hdd_cfg80211_do_acs
9639 },
9640
9641 {
9642 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9643 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9644 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9645 WIPHY_VENDOR_CMD_NEED_NETDEV,
9646 .doit = wlan_hdd_cfg80211_get_features
9647 },
9648#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9649 {
9650 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9651 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9652 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9653 WIPHY_VENDOR_CMD_NEED_NETDEV |
9654 WIPHY_VENDOR_CMD_NEED_RUNNING,
9655 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9656 },
9657#endif
9658#ifdef FEATURE_WLAN_EXTSCAN
9659 {
9660 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9661 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9662 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9663 WIPHY_VENDOR_CMD_NEED_NETDEV |
9664 WIPHY_VENDOR_CMD_NEED_RUNNING,
9665 .doit = wlan_hdd_cfg80211_set_passpoint_list
9666 },
9667 {
9668 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9669 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9671 WIPHY_VENDOR_CMD_NEED_NETDEV |
9672 WIPHY_VENDOR_CMD_NEED_RUNNING,
9673 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9674 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009675#endif /* FEATURE_WLAN_EXTSCAN */
9676 {
9677 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9678 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9679 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9680 WIPHY_VENDOR_CMD_NEED_NETDEV,
9681 .doit = wlan_hdd_cfg80211_get_wifi_info
9682 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009683#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009684 {
9685 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9686 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9687 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9688 WIPHY_VENDOR_CMD_NEED_NETDEV |
9689 WIPHY_VENDOR_CMD_NEED_RUNNING,
9690 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9691 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009692#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009693 {
9694 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9695 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9696 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9697 WIPHY_VENDOR_CMD_NEED_NETDEV,
9698 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9699 },
9700 {
9701 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9702 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9703 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9704 WIPHY_VENDOR_CMD_NEED_NETDEV,
9705 .doit = wlan_hdd_cfg80211_wifi_logger_start
9706 },
9707 {
9708 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9709 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9710 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9711 WIPHY_VENDOR_CMD_NEED_NETDEV,
9712 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9713 },
9714 {
9715 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9716 .info.subcmd =
9717 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9718 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9719 WIPHY_VENDOR_CMD_NEED_NETDEV |
9720 WIPHY_VENDOR_CMD_NEED_RUNNING,
9721 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9722 },
9723 {
9724 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9725 .info.subcmd =
9726 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9727 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9728 WIPHY_VENDOR_CMD_NEED_NETDEV |
9729 WIPHY_VENDOR_CMD_NEED_RUNNING,
9730 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9731 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009732#ifdef WLAN_FEATURE_TSF
9733 {
9734 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9735 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9736 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9737 WIPHY_VENDOR_CMD_NEED_NETDEV |
9738 WIPHY_VENDOR_CMD_NEED_RUNNING,
9739 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9740 },
9741#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009742#ifdef FEATURE_WLAN_TDLS
9743 {
9744 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9745 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9746 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9747 WIPHY_VENDOR_CMD_NEED_NETDEV |
9748 WIPHY_VENDOR_CMD_NEED_RUNNING,
9749 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9750 },
9751#endif
9752#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9753 {
9754 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9755 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9756 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9757 WIPHY_VENDOR_CMD_NEED_NETDEV |
9758 WIPHY_VENDOR_CMD_NEED_RUNNING,
9759 .doit = wlan_hdd_cfg80211_offloaded_packets
9760 },
9761#endif
9762 {
9763 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9764 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9765 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9766 WIPHY_VENDOR_CMD_NEED_NETDEV |
9767 WIPHY_VENDOR_CMD_NEED_RUNNING,
9768 .doit = wlan_hdd_cfg80211_monitor_rssi
9769 },
9770 {
9771 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309772 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9773 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9774 WIPHY_VENDOR_CMD_NEED_NETDEV |
9775 WIPHY_VENDOR_CMD_NEED_RUNNING,
9776 .doit = wlan_hdd_cfg80211_set_ns_offload
9777 },
9778 {
9779 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009780 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9781 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9782 WIPHY_VENDOR_CMD_NEED_NETDEV |
9783 WIPHY_VENDOR_CMD_NEED_RUNNING,
9784 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9785 },
9786#ifdef WLAN_FEATURE_MEMDUMP
9787 {
9788 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9789 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9790 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9791 WIPHY_VENDOR_CMD_NEED_NETDEV |
9792 WIPHY_VENDOR_CMD_NEED_RUNNING,
9793 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9794 },
9795#endif /* WLAN_FEATURE_MEMDUMP */
9796 {
9797 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9798 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9799 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9800 WIPHY_VENDOR_CMD_NEED_NETDEV |
9801 WIPHY_VENDOR_CMD_NEED_RUNNING,
9802 .doit = wlan_hdd_cfg80211_vendor_scan
9803 },
9804
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309805 /* Vendor abort scan */
9806 {
9807 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9808 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9809 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9810 WIPHY_VENDOR_CMD_NEED_NETDEV |
9811 WIPHY_VENDOR_CMD_NEED_RUNNING,
9812 .doit = wlan_hdd_vendor_abort_scan
9813 },
9814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009815 /* OCB commands */
9816 {
9817 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9818 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9819 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9820 WIPHY_VENDOR_CMD_NEED_NETDEV |
9821 WIPHY_VENDOR_CMD_NEED_RUNNING,
9822 .doit = wlan_hdd_cfg80211_ocb_set_config
9823 },
9824 {
9825 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9826 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9827 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9828 WIPHY_VENDOR_CMD_NEED_NETDEV |
9829 WIPHY_VENDOR_CMD_NEED_RUNNING,
9830 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9831 },
9832 {
9833 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9834 .info.subcmd =
9835 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9836 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9837 WIPHY_VENDOR_CMD_NEED_NETDEV |
9838 WIPHY_VENDOR_CMD_NEED_RUNNING,
9839 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9840 },
9841 {
9842 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9843 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9844 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9845 WIPHY_VENDOR_CMD_NEED_NETDEV |
9846 WIPHY_VENDOR_CMD_NEED_RUNNING,
9847 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9848 },
9849 {
9850 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9851 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9852 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9853 WIPHY_VENDOR_CMD_NEED_NETDEV |
9854 WIPHY_VENDOR_CMD_NEED_RUNNING,
9855 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9856 },
9857 {
9858 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9859 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9860 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9861 WIPHY_VENDOR_CMD_NEED_NETDEV |
9862 WIPHY_VENDOR_CMD_NEED_RUNNING,
9863 .doit = wlan_hdd_cfg80211_dcc_get_stats
9864 },
9865 {
9866 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9867 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9868 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9869 WIPHY_VENDOR_CMD_NEED_NETDEV |
9870 WIPHY_VENDOR_CMD_NEED_RUNNING,
9871 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9872 },
9873 {
9874 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9875 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9876 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9877 WIPHY_VENDOR_CMD_NEED_NETDEV |
9878 WIPHY_VENDOR_CMD_NEED_RUNNING,
9879 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9880 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309881 {
9882 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9883 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9884 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9885 WIPHY_VENDOR_CMD_NEED_NETDEV |
9886 WIPHY_VENDOR_CMD_NEED_RUNNING,
9887 .doit = wlan_hdd_cfg80211_get_link_properties
9888 },
Peng Xu278d0122015-09-24 16:34:17 -07009889 {
Peng Xud2220962016-07-11 17:59:17 -07009890 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009891 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9892 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9893 WIPHY_VENDOR_CMD_NEED_NETDEV |
9894 WIPHY_VENDOR_CMD_NEED_RUNNING,
9895 .doit = wlan_hdd_cfg80211_set_ota_test
9896 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009897#ifdef FEATURE_LFR_SUBNET_DETECTION
9898 {
9899 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9900 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9901 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9902 WIPHY_VENDOR_CMD_NEED_NETDEV |
9903 WIPHY_VENDOR_CMD_NEED_RUNNING,
9904 .doit = wlan_hdd_cfg80211_set_gateway_params
9905 },
9906#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009907 {
Peng Xud2220962016-07-11 17:59:17 -07009908 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009909 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9910 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9911 WIPHY_VENDOR_CMD_NEED_NETDEV |
9912 WIPHY_VENDOR_CMD_NEED_RUNNING,
9913 .doit = wlan_hdd_cfg80211_txpower_scale
9914 },
9915 {
9916 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9917 .info.subcmd =
9918 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9919 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9920 WIPHY_VENDOR_CMD_NEED_NETDEV |
9921 WIPHY_VENDOR_CMD_NEED_RUNNING,
9922 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9923 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309924 {
9925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9928 WIPHY_VENDOR_CMD_NEED_NETDEV |
9929 WIPHY_VENDOR_CMD_NEED_RUNNING,
9930 .doit = wlan_hdd_cfg80211_bpf_offload
9931 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309932 {
9933 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309934 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9935 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9936 WIPHY_VENDOR_CMD_NEED_NETDEV |
9937 WIPHY_VENDOR_CMD_NEED_RUNNING,
9938 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9939 },
9940 {
9941 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309942 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9943 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9944 WIPHY_VENDOR_CMD_NEED_NETDEV |
9945 WIPHY_VENDOR_CMD_NEED_RUNNING,
9946 .doit = wlan_hdd_cfg80211_sta_roam_policy
9947 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309948#ifdef FEATURE_WLAN_CH_AVOID
9949 {
9950 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9951 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9952 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9953 WIPHY_VENDOR_CMD_NEED_NETDEV |
9954 WIPHY_VENDOR_CMD_NEED_RUNNING,
9955 .doit = wlan_hdd_cfg80211_avoid_freq
9956 },
9957#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309958 {
9959 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309960 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9961 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9962 WIPHY_VENDOR_CMD_NEED_NETDEV |
9963 WIPHY_VENDOR_CMD_NEED_RUNNING,
9964 .doit = wlan_hdd_cfg80211_sap_configuration_set
9965 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009966 {
Peng Xu4225c152016-07-14 21:18:14 -07009967 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009968 .info.subcmd =
9969 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9970 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9971 WIPHY_VENDOR_CMD_NEED_NETDEV |
9972 WIPHY_VENDOR_CMD_NEED_RUNNING,
9973 .doit = wlan_hdd_cfg80211_p2p_lo_start
9974 },
9975 {
9976 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9977 .info.subcmd =
9978 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9979 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9980 WIPHY_VENDOR_CMD_NEED_NETDEV |
9981 WIPHY_VENDOR_CMD_NEED_RUNNING,
9982 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9983 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309984 {
9985 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9986 .info.subcmd =
9987 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9988 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9989 WIPHY_VENDOR_CMD_NEED_NETDEV |
9990 WIPHY_VENDOR_CMD_NEED_RUNNING,
9991 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9992 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009993#ifdef WLAN_FEATURE_NAN_DATAPATH
9994 {
9995 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9996 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9997 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9998 WIPHY_VENDOR_CMD_NEED_NETDEV |
9999 WIPHY_VENDOR_CMD_NEED_RUNNING,
10000 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10001 },
10002#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010003 {
10004 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10005 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10006 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10007 WIPHY_VENDOR_CMD_NEED_NETDEV |
10008 WIPHY_VENDOR_CMD_NEED_RUNNING,
10009 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10010 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010011 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010012 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10013 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10014 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10015 WIPHY_VENDOR_CMD_NEED_NETDEV |
10016 WIPHY_VENDOR_CMD_NEED_RUNNING,
10017 .doit = wlan_hdd_cfg80211_get_bus_size
10018 },
10019 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010020 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10021 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10022 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10023 WIPHY_VENDOR_CMD_NEED_NETDEV |
10024 WIPHY_VENDOR_CMD_NEED_RUNNING,
10025 .doit = wlan_hdd_cfg80211_update_vendor_channel
10026 },
10027 {
bingsd09dea32017-03-17 10:08:26 +080010028 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010029 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10030 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10031 WIPHY_VENDOR_CMD_NEED_NETDEV |
10032 WIPHY_VENDOR_CMD_NEED_RUNNING,
10033 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010034 },
10035 {
10036 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10037 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10038 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10039 WIPHY_VENDOR_CMD_NEED_NETDEV |
10040 WIPHY_VENDOR_CMD_NEED_RUNNING,
10041 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010042 },
10043#ifdef WLAN_FEATURE_DISA
10044 {
10045 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10046 .info.subcmd =
10047 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10048 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10049 WIPHY_VENDOR_CMD_NEED_NETDEV |
10050 WIPHY_VENDOR_CMD_NEED_RUNNING,
10051 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10052 },
10053#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010054#ifdef FEATURE_WLAN_TDLS
10055 {
10056 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10057 .info.subcmd =
10058 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10059 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10060 WIPHY_VENDOR_CMD_NEED_NETDEV |
10061 WIPHY_VENDOR_CMD_NEED_RUNNING,
10062 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010063 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010064#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010065 {
10066 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10067 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10068 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10069 WIPHY_VENDOR_CMD_NEED_RUNNING,
10070 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10071 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010072 {
10073 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10074 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10075 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10076 WIPHY_VENDOR_CMD_NEED_NETDEV |
10077 WIPHY_VENDOR_CMD_NEED_RUNNING,
10078 .doit = wlan_hdd_cfg80211_set_trace_level
10079 },
10080
Paul Zhang3a210c52016-12-08 10:18:12 +080010081#ifdef WLAN_UMAC_CONVERGENCE
10082 COMMON_VENDOR_COMMANDS
10083#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010084 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010085};
10086
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010087#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10088 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10089 defined(FEATURE_WLAN_SCAN_PNO)
10090/**
10091 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10092 * @wiphy: pointer to wiphy
10093 * @config: pointer to config
10094 *
10095 * Return: None
10096 */
10097static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10098 struct hdd_config *config)
10099{
10100 if (config->configPNOScanSupport) {
10101 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010102 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10103 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010104 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010105 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010106 if (config->max_sched_scan_plan_interval)
10107 wiphy->max_sched_scan_plan_interval =
10108 config->max_sched_scan_plan_interval;
10109 if (config->max_sched_scan_plan_iterations)
10110 wiphy->max_sched_scan_plan_iterations =
10111 config->max_sched_scan_plan_iterations;
10112 }
10113}
10114#else
10115static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10116 struct hdd_config *config)
10117{
10118}
10119#endif
10120
10121
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010122/**
10123 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10124 * @priv_size: Size of the hdd context.
10125 *
10126 * Allocate wiphy context and hdd context.
10127 *
10128 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010129 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010130hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010131{
10132 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010133 hdd_context_t *hdd_ctx;
10134
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135 ENTER();
10136
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010137 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10138
10139 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010140 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010141 return NULL;
10142 }
10143
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010144 hdd_ctx = wiphy_priv(wiphy);
10145
10146 hdd_ctx->wiphy = wiphy;
10147
10148 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010149}
10150
10151/*
10152 * FUNCTION: wlan_hdd_cfg80211_update_band
10153 * This function is called from the supplicant through a
10154 * private ioctl to change the band value
10155 */
10156int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10157{
10158 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010159 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010160
10161 ENTER();
10162
Dustin Browna30892e2016-10-12 17:28:36 -070010163 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010164
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010165 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010166 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010167
10168 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10169 struct ieee80211_supported_band *band = wiphy->bands[i];
10170
10171 channelEnabledState =
10172 cds_get_channel_state(band->channels[j].
10173 hw_value);
10174
Dustin Browna30892e2016-10-12 17:28:36 -070010175 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010176 /* 5G only */
10177#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10178 /* Enable Social channels for P2P */
10179 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10180 (band->channels[j].center_freq)
10181 && CHANNEL_STATE_ENABLE ==
10182 channelEnabledState)
10183 band->channels[j].flags &=
10184 ~IEEE80211_CHAN_DISABLED;
10185 else
10186#endif
10187 band->channels[j].flags |=
10188 IEEE80211_CHAN_DISABLED;
10189 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010190 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010191 eCSR_BAND_24 == eBand) {
10192 /* 2G only */
10193 band->channels[j].flags |=
10194 IEEE80211_CHAN_DISABLED;
10195 continue;
10196 }
10197
Amar Singhal6842e8f2016-02-23 16:30:32 -080010198 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010199 band->channels[j].flags &=
10200 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010201 }
10202 }
10203 return 0;
10204}
10205
Peng Xuacfdda12017-02-06 16:15:38 -080010206#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010207/*
10208 * FUNCTION: wlan_hdd_cfg80211_init
10209 * This function is called by hdd_wlan_startup()
10210 * during initialization.
10211 * This function is used to initialize and register wiphy structure.
10212 */
10213int wlan_hdd_cfg80211_init(struct device *dev,
10214 struct wiphy *wiphy, struct hdd_config *pCfg)
10215{
10216 int i, j;
10217 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10218
10219 ENTER();
10220
10221 /* Now bind the underlying wlan device with wiphy */
10222 set_wiphy_dev(wiphy, dev);
10223
10224 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10225
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010226 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10227 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10228 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10229#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10230 | WIPHY_FLAG_4ADDR_STATION
10231#endif
10232 | WIPHY_FLAG_OFFCHAN_TX;
10233
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010234#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10235 wiphy->wowlan = &wowlan_support_cfg80211_init;
10236#else
10237 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10238 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10239 wiphy->wowlan.pattern_min_len = 1;
10240 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10241#endif
10242
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010243 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010244#ifdef FEATURE_WLAN_ESE
10245 || pCfg->isEseIniFeatureEnabled
10246#endif
10247 ) {
10248 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10249 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010250#ifdef FEATURE_WLAN_TDLS
10251 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10252 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10253#endif
10254
10255 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10256
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010257#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10258 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10259#endif
10260
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010261 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010262
10263#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010264 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010265#endif
10266
10267 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010268 * driver can still register regulatory callback and
10269 * it will get regulatory settings in wiphy->band[], but
10270 * driver need to determine what to do with both
10271 * regulatory settings
10272 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010274#if defined QCA_WIFI_FTM
10275}
10276#endif
10277
10278 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10279
10280 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10281
10282 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10283
Arun Khandavallifae92942016-08-01 13:31:08 +053010284 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10285 | BIT(NL80211_IFTYPE_ADHOC)
10286 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10287 | BIT(NL80211_IFTYPE_P2P_GO)
10288 | BIT(NL80211_IFTYPE_AP)
10289 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010290
Arun Khandavallifae92942016-08-01 13:31:08 +053010291 if (pCfg->advertiseConcurrentOperation) {
10292 if (pCfg->enableMCC) {
10293 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010294
Arun Khandavallifae92942016-08-01 13:31:08 +053010295 for (i = 0;
10296 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10297 i++) {
10298 if (!pCfg->allowMCCGODiffBI)
10299 wlan_hdd_iface_combination[i].
10300 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010301 }
10302 }
10303 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010304 ARRAY_SIZE(wlan_hdd_iface_combination);
10305 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010306 }
10307
10308 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010309 * on ini values
10310 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 if (!pCfg->ShortGI20MhzEnable) {
10312 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10313 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010314 }
10315
10316 if (!pCfg->ShortGI40MhzEnable) {
10317 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10318 }
10319
10320 if (!pCfg->nChannelBondingMode5GHz) {
10321 wlan_hdd_band_5_ghz.ht_cap.cap &=
10322 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10323 }
10324
Abhishek Singhf512bf32016-05-04 16:47:46 +053010325 /*
10326 * In case of static linked driver at the time of driver unload,
10327 * module exit doesn't happens. Module cleanup helps in cleaning
10328 * of static memory.
10329 * If driver load happens statically, at the time of driver unload,
10330 * wiphy flags don't get reset because of static memory.
10331 * It's better not to store channel in static memory.
10332 */
Dustin Browna30892e2016-10-12 17:28:36 -070010333 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10334 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010335 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010336 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010337 hdd_err("Not enough memory to allocate channels");
10338 return -ENOMEM;
10339 }
Dustin Browna30892e2016-10-12 17:28:36 -070010340 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010341 &hdd_channels_2_4_ghz[0],
10342 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010343 if ((hdd_is_5g_supported(pHddCtx)) &&
10344 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10345 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10346 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10347 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010348 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10349 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010350 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010351 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010352 hdd_err("Not enough memory to allocate channels");
10353 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010354 bands[NL80211_BAND_2GHZ]->channels);
10355 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010356 return -ENOMEM;
10357 }
Dustin Browna30892e2016-10-12 17:28:36 -070010358 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010359 &hdd_channels_5_ghz[0],
10360 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010361 }
10362
Dustin Browna30892e2016-10-12 17:28:36 -070010363 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010364
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010365 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010366 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010367
10368 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10369 struct ieee80211_supported_band *band = wiphy->bands[i];
10370
Dustin Browna30892e2016-10-12 17:28:36 -070010371 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010372 eCSR_BAND_5G == pCfg->nBandCapability) {
10373 /* 5G only */
10374#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10375 /* Enable social channels for P2P */
10376 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10377 (band->channels[j].center_freq))
10378 band->channels[j].flags &=
10379 ~IEEE80211_CHAN_DISABLED;
10380 else
10381#endif
10382 band->channels[j].flags |=
10383 IEEE80211_CHAN_DISABLED;
10384 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010385 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010386 eCSR_BAND_24 == pCfg->nBandCapability) {
10387 /* 2G only */
10388 band->channels[j].flags |=
10389 IEEE80211_CHAN_DISABLED;
10390 continue;
10391 }
10392 }
10393 }
10394 /*Initialise the supported cipher suite details */
10395 wiphy->cipher_suites = hdd_cipher_suites;
10396 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10397
10398 /*signal strength in mBm (100*dBm) */
10399 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10400 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10401
Anurag Chouhan6d760662016-02-20 16:05:43 +053010402 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010403 wiphy->n_vendor_commands =
10404 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10405 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10406
10407 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10408 wiphy->n_vendor_events =
10409 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10410 }
10411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010412 if (pCfg->enableDFSMasterCap) {
10413 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10414 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010415
10416 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10417
10418#ifdef QCA_HT_2040_COEX
10419 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10420#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010421 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010422
10423#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10424 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10425 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10426 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10427 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10428#endif
10429
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010430 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010431 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010432
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010433 EXIT();
10434 return 0;
10435}
10436
Abhishek Singhf512bf32016-05-04 16:47:46 +053010437/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010438 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10439 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010440 *
10441 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010442 * memory allocated in wlan_hdd_cfg80211_init also
10443 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010444 *
10445 * Return: void
10446 */
10447void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10448{
10449 int i;
10450
Dustin Browna30892e2016-10-12 17:28:36 -070010451 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010452 if (NULL != wiphy->bands[i] &&
10453 (NULL != wiphy->bands[i]->channels)) {
10454 qdf_mem_free(wiphy->bands[i]->channels);
10455 wiphy->bands[i]->channels = NULL;
10456 }
10457 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010458
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010459 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010460}
10461
Yingying Tang80e15f32016-09-27 18:23:01 +080010462/**
10463 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10464 * @hdd_ctx: HDD context
10465 *
10466 * this function will update capabilities for supported bands
10467 *
10468 * Return: void
10469 */
10470static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10471{
10472 uint32_t val32;
10473 uint16_t val16;
10474 tSirMacHTCapabilityInfo *ht_cap_info;
10475 QDF_STATUS status;
10476
10477 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10478 if (QDF_STATUS_SUCCESS != status) {
10479 hdd_err("could not get HT capability info");
10480 val32 = 0;
10481 }
10482 val16 = (uint16_t)val32;
10483 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10484
10485 if (ht_cap_info->txSTBC == true) {
10486 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10487 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10488 IEEE80211_HT_CAP_TX_STBC;
10489 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10490 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10491 IEEE80211_HT_CAP_TX_STBC;
10492 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010493
10494 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10495 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10496 vht_cap.vht_supported = 0;
10497 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10498 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10499 vht_cap.vht_supported = 0;
10500 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10501 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010502}
10503
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010504/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010505 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010506 * initialization. In wlan_hdd_cfg80211_init, only the
10507 * default values will be initialized. The final initialization
10508 * of all required members can be done here.
10509 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010510void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010511{
Yingying Tang80e15f32016-09-27 18:23:01 +080010512 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10513
10514 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010515}
10516
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010517/**
10518 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10519 * @cfg: hdd cfg
10520 *
10521 * this function update 11n mode in hdd cfg
10522 *
10523 * Return: void
10524 */
10525void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10526{
10527 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010528 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010529 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010530 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010531 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10532 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10533 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10534 cfg->sap_p2p_11ac_override = 0;
10535 }
10536 }
10537}
10538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010539/* In this function we are registering wiphy. */
10540int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10541{
10542 ENTER();
10543 /* Register our wiphy dev with cfg80211 */
10544 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010545 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010546 return -EIO;
10547 }
10548
10549 EXIT();
10550 return 0;
10551}
10552
10553/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010554 * HDD function to update wiphy capability based on target offload status.
10555 *
10556 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10557 * capability even before downloading firmware to the target. In discrete
10558 * case, host will get know certain offload capability (say sched_scan
10559 * caps) only after downloading firmware to the target and target boots up.
10560 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10561 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010562 */
10563void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10564{
10565#ifdef FEATURE_WLAN_SCAN_PNO
10566 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10567 struct hdd_config *pCfg = pHddCtx->config;
10568
10569 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10570 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010571 * have PNO support.
10572 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010573 if (!pCfg->PnoOffload) {
10574 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10575 wiphy->max_sched_scan_ssids = 0;
10576 wiphy->max_match_sets = 0;
10577 wiphy->max_sched_scan_ie_len = 0;
10578 }
10579#endif
10580}
10581
10582/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010583#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10584
Wu Gao84d120c2017-03-24 18:46:00 +080010585void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10586{
10587 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10588 /* Register for all P2P action, public action etc frames */
10589 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10590
10591 ENTER();
10592
10593 /* Register frame indication call back */
10594 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10595
10596 /* Register for p2p ack indication */
10597 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10598
10599 /* Right now we are registering these frame when driver is getting
10600 * initialized. Once we will move to 2.6.37 kernel, in which we have
10601 * frame register ops, we will move this code as a part of that
10602 */
10603
10604 /* GAS Initial Request */
10605 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10606 (uint8_t *) GAS_INITIAL_REQ,
10607 GAS_INITIAL_REQ_SIZE);
10608
10609 /* GAS Initial Response */
10610 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10611 (uint8_t *) GAS_INITIAL_RSP,
10612 GAS_INITIAL_RSP_SIZE);
10613
10614 /* GAS Comeback Request */
10615 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10616 (uint8_t *) GAS_COMEBACK_REQ,
10617 GAS_COMEBACK_REQ_SIZE);
10618
10619 /* GAS Comeback Response */
10620 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10621 (uint8_t *) GAS_COMEBACK_RSP,
10622 GAS_COMEBACK_RSP_SIZE);
10623
10624 /* WNM BSS Transition Request frame */
10625 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10626 (uint8_t *) WNM_BSS_ACTION_FRAME,
10627 WNM_BSS_ACTION_FRAME_SIZE);
10628
10629 /* WNM-Notification */
10630 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10631 (uint8_t *) WNM_NOTIFICATION_FRAME,
10632 WNM_NOTIFICATION_FRAME_SIZE);
10633}
10634#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010635void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10636{
10637 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10638 /* Register for all P2P action, public action etc frames */
10639 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10640
10641 ENTER();
10642
Abhishek Singh7996eb72015-12-30 17:24:02 +053010643 /* Register frame indication call back */
10644 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10645
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010646 /* Register for p2p ack indication */
10647 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10648
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010649 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010650 * initialized. Once we will move to 2.6.37 kernel, in which we have
10651 * frame register ops, we will move this code as a part of that
10652 */
10653
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010654 /* GAS Initial Request */
10655 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10656 (uint8_t *) GAS_INITIAL_REQ,
10657 GAS_INITIAL_REQ_SIZE);
10658
10659 /* GAS Initial Response */
10660 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10661 (uint8_t *) GAS_INITIAL_RSP,
10662 GAS_INITIAL_RSP_SIZE);
10663
10664 /* GAS Comeback Request */
10665 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10666 (uint8_t *) GAS_COMEBACK_REQ,
10667 GAS_COMEBACK_REQ_SIZE);
10668
10669 /* GAS Comeback Response */
10670 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10671 (uint8_t *) GAS_COMEBACK_RSP,
10672 GAS_COMEBACK_RSP_SIZE);
10673
10674 /* P2P Public Action */
10675 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10676 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10677 P2P_PUBLIC_ACTION_FRAME_SIZE);
10678
10679 /* P2P Action */
10680 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10681 (uint8_t *) P2P_ACTION_FRAME,
10682 P2P_ACTION_FRAME_SIZE);
10683
10684 /* WNM BSS Transition Request frame */
10685 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10686 (uint8_t *) WNM_BSS_ACTION_FRAME,
10687 WNM_BSS_ACTION_FRAME_SIZE);
10688
10689 /* WNM-Notification */
10690 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10691 (uint8_t *) WNM_NOTIFICATION_FRAME,
10692 WNM_NOTIFICATION_FRAME_SIZE);
10693}
Wu Gao84d120c2017-03-24 18:46:00 +080010694#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010695
10696void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10697{
10698 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10699 /* Register for all P2P action, public action etc frames */
10700 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10701
10702 ENTER();
10703
10704 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010705 * initialized. Once we will move to 2.6.37 kernel, in which we have
10706 * frame register ops, we will move this code as a part of that
10707 */
10708
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010709 /* GAS Initial Request */
10710
10711 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10712 (uint8_t *) GAS_INITIAL_REQ,
10713 GAS_INITIAL_REQ_SIZE);
10714
10715 /* GAS Initial Response */
10716 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10717 (uint8_t *) GAS_INITIAL_RSP,
10718 GAS_INITIAL_RSP_SIZE);
10719
10720 /* GAS Comeback Request */
10721 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10722 (uint8_t *) GAS_COMEBACK_REQ,
10723 GAS_COMEBACK_REQ_SIZE);
10724
10725 /* GAS Comeback Response */
10726 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10727 (uint8_t *) GAS_COMEBACK_RSP,
10728 GAS_COMEBACK_RSP_SIZE);
10729
10730 /* P2P Public Action */
10731 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10732 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10733 P2P_PUBLIC_ACTION_FRAME_SIZE);
10734
10735 /* P2P Action */
10736 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10737 (uint8_t *) P2P_ACTION_FRAME,
10738 P2P_ACTION_FRAME_SIZE);
10739
10740 /* WNM-Notification */
10741 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10742 (uint8_t *) WNM_NOTIFICATION_FRAME,
10743 WNM_NOTIFICATION_FRAME_SIZE);
10744}
10745
10746#ifdef FEATURE_WLAN_WAPI
10747void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10748 const uint8_t *mac_addr, const uint8_t *key,
10749 int key_Len)
10750{
10751 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10752 tCsrRoamSetKey setKey;
10753 bool isConnected = true;
10754 int status = 0;
10755 uint32_t roamId = 0xFF;
10756 uint8_t *pKeyPtr = NULL;
10757 int n = 0;
10758
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010759 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760 hdd_device_mode_to_string(pAdapter->device_mode),
10761 pAdapter->device_mode);
10762
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010763 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010764 setKey.keyId = key_index; /* Store Key ID */
10765 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10766 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10767 setKey.paeRole = 0; /* the PAE role */
10768 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010769 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010770 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010771 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010772 }
10773 setKey.keyLength = key_Len;
10774 pKeyPtr = setKey.Key;
10775 memcpy(pKeyPtr, key, key_Len);
10776
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010777 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010778 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010779 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010780 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010781
10782 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10783 if (isConnected) {
10784 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10785 pAdapter->sessionId, &setKey, &roamId);
10786 }
10787 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010788 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010789 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10790 }
10791}
10792#endif /* FEATURE_WLAN_WAPI */
10793
10794uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10795 uint8_t eid)
10796{
10797 int left = length;
10798 uint8_t *ptr = (uint8_t *)ies_ptr;
10799 uint8_t elem_id, elem_len;
10800
10801 while (left >= 2) {
10802 elem_id = ptr[0];
10803 elem_len = ptr[1];
10804 left -= 2;
10805 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010806 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010807 eid, elem_len, left);
10808 return NULL;
10809 }
10810 if (elem_id == eid) {
10811 return ptr;
10812 }
10813
10814 left -= elem_len;
10815 ptr += (elem_len + 2);
10816 }
10817 return NULL;
10818}
10819
10820/*
10821 * FUNCTION: wlan_hdd_validate_operation_channel
10822 * called by wlan_hdd_cfg80211_start_bss() and
10823 * wlan_hdd_set_channel()
10824 * This function validates whether given channel is part of valid
10825 * channel list.
10826 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010827QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010828 int channel)
10829{
10830
10831 uint32_t num_ch = 0;
10832 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10833 u32 indx = 0;
10834 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10835 uint8_t fValidChannel = false, count = 0;
10836 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10837
10838 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10839
10840 if (hdd_pConfig_ini->sapAllowAllChannel) {
10841 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010842 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010843 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010844 fValidChannel = true;
10845 break;
10846 }
10847 }
10848 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010849 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010850 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010851 }
10852 } else {
10853 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10854 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010855 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010856 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010857 }
10858 for (indx = 0; indx < num_ch; indx++) {
10859 if (channel == valid_ch[indx]) {
10860 break;
10861 }
10862 }
10863
10864 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010865 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010866 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010867 }
10868 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010869 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010870
10871}
10872
10873#ifdef DHCP_SERVER_OFFLOAD
10874static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10875{
10876 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10877 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10878 uint8_t numEntries = 0;
10879 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10880 uint8_t num;
10881 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010882 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010883 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010884 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010885 return;
10886 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10888 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10889 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10890 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10891 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10892 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010893 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010894 goto end;
10895 }
10896 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010897 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010898 goto end;
10899 }
10900 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010901 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010902 goto end;
10903 }
10904 for (num = 0; num < numEntries; num++) {
10905 temp = srv_ip[num];
10906 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10907 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010908 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010910 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010911 goto end;
10912 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010913 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010914end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010915 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916 return;
10917}
10918#endif /* DHCP_SERVER_OFFLOAD */
10919
10920static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10921 struct net_device *dev,
10922 struct bss_parameters *params)
10923{
10924 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10925 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10926 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010927 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010928
10929 ENTER();
10930
Anurag Chouhan6d760662016-02-20 16:05:43 +053010931 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010932 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010933 return -EINVAL;
10934 }
10935
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010936 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10937 hdd_err("invalid session id: %d", pAdapter->sessionId);
10938 return -EINVAL;
10939 }
10940
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010941 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010942 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10943 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010944 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010945 hdd_device_mode_to_string(pAdapter->device_mode),
10946 pAdapter->device_mode, params->ap_isolate);
10947
10948 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10949 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010950 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010951 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010952
Krunal Sonib4326f22016-03-10 13:05:51 -080010953 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10954 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010955 return -EOPNOTSUPP;
10956 }
10957
10958 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010959 * want to update this parameter
10960 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010961 if (-1 != params->ap_isolate) {
10962 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10963 !!params->ap_isolate;
10964
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010965 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010966 pAdapter->sessionId,
10967 pAdapter->sessionCtx.
10968 ap.
10969 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010970 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010971 ret = -EINVAL;
10972 }
10973 }
10974
10975 EXIT();
10976 return ret;
10977}
10978
Krunal Soni8c37e322016-02-03 16:08:37 -080010979/**
10980 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10981 * @ndev: pointer to net device provided by supplicant
10982 * @type: type of the interface, upper layer wanted to change
10983 *
10984 * Upper layer provides the new interface mode that needs to be changed
10985 * for given net device
10986 *
10987 * Return: success or failure in terms of integer value
10988 */
10989static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010990 enum nl80211_iftype type)
10991{
Krunal Soni8c37e322016-02-03 16:08:37 -080010992 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10993 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10994 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010995 hdd_wext_state_t *wext;
10996 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010997 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010998
10999 ENTER();
11000
Krunal Soni8c37e322016-02-03 16:08:37 -080011001 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011002 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011003 return 0;
11004 }
11005
11006 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011007 hdd_stop_adapter(hdd_ctx, adapter, true);
11008 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011009 wdev->iftype = type;
11010 /*Check for sub-string p2p to confirm its a p2p interface */
11011 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011012 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011013 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011014 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011015 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011016 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011017 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011018 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011019 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011020 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011021 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011022 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11023 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011024 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11025 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011026 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011027 adapter->scan_info.scanAddIE.length;
11028 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011029 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011030 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11031 wext->roamProfile.phyMode =
11032 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11033 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011034 EXIT();
11035 return status;
11036}
11037
11038static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11039 struct net_device *dev,
11040 struct bss_parameters *params)
11041{
11042 int ret;
11043
11044 cds_ssr_protect(__func__);
11045 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11046 cds_ssr_unprotect(__func__);
11047
11048 return ret;
11049}
11050
11051/* FUNCTION: wlan_hdd_change_country_code_cd
11052 * to wait for contry code completion
11053 */
11054void *wlan_hdd_change_country_code_cb(void *pAdapter)
11055{
11056 hdd_adapter_t *call_back_pAdapter = pAdapter;
11057 complete(&call_back_pAdapter->change_country_code);
11058 return NULL;
11059}
11060
Rajeev Kumar98edb772016-01-19 12:42:19 -080011061/**
11062 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11063 * @wiphy: Pointer to the wiphy structure
11064 * @ndev: Pointer to the net device
11065 * @type: Interface type
11066 * @flags: Flags for change interface
11067 * @params: Pointer to change interface parameters
11068 *
11069 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011070 */
11071static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11072 struct net_device *ndev,
11073 enum nl80211_iftype type,
11074 u32 *flags,
11075 struct vif_params *params)
11076{
11077 struct wireless_dev *wdev;
11078 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11079 hdd_context_t *pHddCtx;
11080 tCsrRoamProfile *pRoamProfile = NULL;
11081 eCsrRoamBssType LastBSSType;
11082 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011083 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011084 int status;
11085
11086 ENTER();
11087
Anurag Chouhan6d760662016-02-20 16:05:43 +053011088 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011089 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011090 return -EINVAL;
11091 }
11092
11093 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11094 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011095 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011097
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011098 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11100 pAdapter->sessionId, type));
11101
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011102 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011103 pAdapter->device_mode, type);
11104
Arun Khandavallifae92942016-08-01 13:31:08 +053011105 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11106 if (status) {
11107 hdd_err("Failed to start modules");
11108 return -EINVAL;
11109 }
11110
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011111 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011112 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11113 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011114 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011115 return -EINVAL;
11116 }
11117
11118 pConfig = pHddCtx->config;
11119 wdev = ndev->ieee80211_ptr;
11120
11121 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011122 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11123 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011124
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011125 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011126 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011127 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11128 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11129 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11130 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011131 hdd_wext_state_t *pWextState =
11132 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11133
11134 pRoamProfile = &pWextState->roamProfile;
11135 LastBSSType = pRoamProfile->BSSType;
11136
11137 switch (type) {
11138 case NL80211_IFTYPE_STATION:
11139 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011140 case NL80211_IFTYPE_ADHOC:
11141 if (type == NL80211_IFTYPE_ADHOC) {
11142 wlan_hdd_tdls_exit(pAdapter);
11143 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011144 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011145 }
11146 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11147 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011148 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011149 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011150 if (hdd_start_adapter(pAdapter)) {
11151 hdd_err("Failed to start adapter :%d",
11152 pAdapter->device_mode);
11153 return -EINVAL;
11154 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011155 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011156 case NL80211_IFTYPE_AP:
11157 case NL80211_IFTYPE_P2P_GO:
11158 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011159 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011160 (type ==
11161 NL80211_IFTYPE_AP) ? "SoftAP" :
11162 "P2pGo");
11163
11164 /* Cancel any remain on channel for GO mode */
11165 if (NL80211_IFTYPE_P2P_GO == type) {
11166 wlan_hdd_cancel_existing_remain_on_channel
11167 (pAdapter);
11168 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011169
Arun Khandavallifae92942016-08-01 13:31:08 +053011170 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011171 /* De-init the adapter */
11172 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11173 memset(&pAdapter->sessionCtx, 0,
11174 sizeof(pAdapter->sessionCtx));
11175 pAdapter->device_mode =
11176 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011177 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11178 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011179
11180 /*
11181 * Fw will take care incase of concurrency
11182 */
11183
Krunal Sonib4326f22016-03-10 13:05:51 -080011184 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011185 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011186 /* To meet Android requirements create
11187 * a randomized MAC address of the
11188 * form 02:1A:11:Fx:xx:xx
11189 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011190 get_random_bytes(&ndev->dev_addr[3], 3);
11191 ndev->dev_addr[0] = 0x02;
11192 ndev->dev_addr[1] = 0x1A;
11193 ndev->dev_addr[2] = 0x11;
11194 ndev->dev_addr[3] |= 0xF0;
11195 memcpy(pAdapter->macAddressCurrent.
11196 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011197 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011198 pr_info("wlan: Generated HotSpot BSSID "
11199 MAC_ADDRESS_STR "\n",
11200 MAC_ADDR_ARRAY(ndev->dev_addr));
11201 }
11202
11203 hdd_set_ap_ops(pAdapter->dev);
11204
Arun Khandavallifae92942016-08-01 13:31:08 +053011205 if (hdd_start_adapter(pAdapter)) {
11206 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011207 return -EINVAL;
11208 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011209 /* Interface type changed update in wiphy structure */
11210 if (wdev) {
11211 wdev->iftype = type;
11212 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011213 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011214 return -EINVAL;
11215 }
11216 goto done;
11217 }
11218
11219 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011220 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011221 return -EOPNOTSUPP;
11222 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011223 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11224 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011225 switch (type) {
11226 case NL80211_IFTYPE_STATION:
11227 case NL80211_IFTYPE_P2P_CLIENT:
11228 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011229 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11230 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011231 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011232 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011233 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011234 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011235 pAdapter->device_mode);
11236 return -EINVAL;
11237 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 goto done;
11239
11240 case NL80211_IFTYPE_AP:
11241 case NL80211_IFTYPE_P2P_GO:
11242 wdev->iftype = type;
11243 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011244 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011245 goto done;
11246
11247 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011248 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011249 return -EOPNOTSUPP;
11250 }
11251 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011252 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011253 pAdapter->device_mode);
11254 return -EOPNOTSUPP;
11255 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011256done:
11257 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011258 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11259 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011261 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262
11263 EXIT();
11264 return 0;
11265}
11266
Rajeev Kumar98edb772016-01-19 12:42:19 -080011267/**
11268 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11269 * @wiphy: Pointer to the wiphy structure
11270 * @ndev: Pointer to the net device
11271 * @type: Interface type
11272 * @flags: Flags for change interface
11273 * @params: Pointer to change interface parameters
11274 *
11275 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011276 */
11277static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11278 struct net_device *ndev,
11279 enum nl80211_iftype type,
11280 u32 *flags,
11281 struct vif_params *params)
11282{
11283 int ret;
11284
11285 cds_ssr_protect(__func__);
11286 ret =
11287 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11288 cds_ssr_unprotect(__func__);
11289
11290 return ret;
11291}
11292
Frank Liud4b2fa02017-03-29 11:46:48 +080011293#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011294static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11295 int index, uint8_t match)
11296{
11297 int i;
11298 for (i = 0; i < index; i++) {
11299 if (arr[i] == match)
11300 return true;
11301 }
11302 return false;
11303}
11304#endif
11305
11306/**
11307 * __wlan_hdd_change_station() - change station
11308 * @wiphy: Pointer to the wiphy structure
11309 * @dev: Pointer to the net device.
11310 * @mac: bssid
11311 * @params: Pointer to station parameters
11312 *
11313 * Return: 0 for success, error number on failure.
11314 */
11315#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11316static int __wlan_hdd_change_station(struct wiphy *wiphy,
11317 struct net_device *dev,
11318 const uint8_t *mac,
11319 struct station_parameters *params)
11320#else
11321static int __wlan_hdd_change_station(struct wiphy *wiphy,
11322 struct net_device *dev,
11323 uint8_t *mac,
11324 struct station_parameters *params)
11325#endif
11326{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011327 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011328 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11329 hdd_context_t *pHddCtx;
11330 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011331 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011332#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011333 tCsrStaParams StaParams = { 0 };
11334 uint8_t isBufSta = 0;
11335 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011336 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011337#endif
11338 int ret;
11339
11340 ENTER();
11341
Anurag Chouhan6d760662016-02-20 16:05:43 +053011342 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011343 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011344 return -EINVAL;
11345 }
11346
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011347 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011348 TRACE_CODE_HDD_CHANGE_STATION,
11349 pAdapter->sessionId, params->listen_interval));
11350
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011351 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11352 hdd_err("invalid session id: %d", pAdapter->sessionId);
11353 return -EINVAL;
11354 }
11355
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011356 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11357 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011358 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011359 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011360
11361 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11362
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011363 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011364
Krunal Sonib4326f22016-03-10 13:05:51 -080011365 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11366 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011367 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11368 status =
11369 hdd_softap_change_sta_state(pAdapter,
11370 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011371 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011372
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011373 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011374 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011375 return -EINVAL;
11376 }
11377 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011378 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11379 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011380 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011381#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11382 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11383 dev, mac, params);
11384#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011385
11386 if (cds_is_sub_20_mhz_enabled()) {
11387 hdd_err("TDLS not allowed with sub 20 MHz");
11388 return -EINVAL;
11389 }
11390
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011391 StaParams.capability = params->capability;
11392 StaParams.uapsd_queues = params->uapsd_queues;
11393 StaParams.max_sp = params->max_sp;
11394
11395 /* Convert (first channel , number of channels) tuple to
11396 * the total list of channels. This goes with the assumption
11397 * that if the first channel is < 14, then the next channels
11398 * are an incremental of 1 else an incremental of 4 till the number
11399 * of channels.
11400 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011401 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011402 if (0 != params->supported_channels_len) {
11403 int i = 0, j = 0, k = 0, no_of_channels = 0;
11404 int num_unique_channels;
11405 int next;
11406 for (i = 0;
11407 i < params->supported_channels_len
11408 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11409 int wifi_chan_index;
11410 if (!wlan_hdd_is_duplicate_channel
11411 (StaParams.supported_channels, j,
11412 params->supported_channels[i])) {
11413 StaParams.
11414 supported_channels[j] =
11415 params->
11416 supported_channels[i];
11417 } else {
11418 continue;
11419 }
11420 wifi_chan_index =
11421 ((StaParams.supported_channels[j] <=
11422 HDD_CHANNEL_14) ? 1 : 4);
11423 no_of_channels =
11424 params->supported_channels[i + 1];
11425
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011426 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d", i, j, k, j,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011427 StaParams.
11428 supported_channels[j],
11429 wifi_chan_index,
11430 no_of_channels);
11431 for (k = 1; k <= no_of_channels &&
11432 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11433 k++) {
11434 next =
11435 StaParams.
11436 supported_channels[j] +
11437 wifi_chan_index;
11438 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11439 StaParams.
11440 supported_channels[j
11441 +
11442 1]
11443 = next;
11444 } else {
11445 continue;
11446 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011447 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011448 j + 1,
11449 StaParams.
11450 supported_channels[j +
11451 1]);
11452 j += 1;
11453 }
11454 }
11455 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011456 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011457 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011458 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011459 StaParams.
11460 supported_channels[i]);
11461 }
11462 if (MAX_CHANNEL < num_unique_channels)
11463 num_unique_channels = MAX_CHANNEL;
11464 StaParams.supported_channels_len =
11465 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011466 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011467 StaParams.supported_channels_len);
11468 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011469 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011470 params->supported_oper_classes,
11471 params->supported_oper_classes_len);
11472 StaParams.supported_oper_classes_len =
11473 params->supported_oper_classes_len;
11474
11475 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011476 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011477 params->ext_capab,
11478 sizeof(StaParams.extn_capability));
11479
11480 if (NULL != params->ht_capa) {
11481 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011482 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011483 sizeof(tSirHTCap));
11484 }
11485
11486 StaParams.supported_rates_len =
11487 params->supported_rates_len;
11488
11489 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11490 * The supported_rates array , for all the structures propogating till Add Sta
11491 * to the firmware has to be modified , if the supplicant (ieee80211) is
11492 * modified to send more rates.
11493 */
11494
11495 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11496 */
11497 if (StaParams.supported_rates_len >
11498 SIR_MAC_MAX_SUPP_RATES)
11499 StaParams.supported_rates_len =
11500 SIR_MAC_MAX_SUPP_RATES;
11501
11502 if (0 != StaParams.supported_rates_len) {
11503 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011504 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011505 params->supported_rates,
11506 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011507 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011508 StaParams.supported_rates_len);
11509 for (i = 0; i < StaParams.supported_rates_len;
11510 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011511 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011512 StaParams.supported_rates[i]);
11513 }
11514
11515 if (NULL != params->vht_capa) {
11516 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011517 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011518 params->vht_capa,
11519 sizeof(tSirVHTCap));
11520 }
11521
11522 if (0 != params->ext_capab_len) {
11523 /*Define A Macro : TODO Sunil */
11524 if ((1 << 4) & StaParams.extn_capability[3]) {
11525 isBufSta = 1;
11526 }
11527 /* TDLS Channel Switching Support */
11528 if ((1 << 6) & StaParams.extn_capability[3]) {
11529 isOffChannelSupported = 1;
11530 }
11531 }
11532
Nitesh Shah99934ac2016-09-05 15:54:08 +053011533 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011534 (params->ht_capa || params->vht_capa ||
11535 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011536 is_qos_wmm_sta = true;
11537
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011538 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011539 " is_qos_wmm_sta= %d HTcapPresent = %d",
11540 __func__, is_qos_wmm_sta,
11541 StaParams.htcap_present);
11542
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011543 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011544 &StaParams,
11545 isBufSta,
11546 isOffChannelSupported,
11547 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011548 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011549 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011550 return -EINVAL;
11551 }
11552
11553 status =
11554 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11555 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011556 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011557 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011558 return -EINVAL;
11559 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011560#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011561 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011562 }
11563 EXIT();
11564 return ret;
11565}
11566
11567/**
11568 * wlan_hdd_change_station() - cfg80211 change station handler function
11569 * @wiphy: Pointer to the wiphy structure
11570 * @dev: Pointer to the net device.
11571 * @mac: bssid
11572 * @params: Pointer to station parameters
11573 *
11574 * This is the cfg80211 change station handler function which invokes
11575 * the internal function @__wlan_hdd_change_station with
11576 * SSR protection.
11577 *
11578 * Return: 0 for success, error number on failure.
11579 */
11580#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11581static int wlan_hdd_change_station(struct wiphy *wiphy,
11582 struct net_device *dev,
11583 const u8 *mac,
11584 struct station_parameters *params)
11585#else
11586static int wlan_hdd_change_station(struct wiphy *wiphy,
11587 struct net_device *dev,
11588 u8 *mac,
11589 struct station_parameters *params)
11590#endif
11591{
11592 int ret;
11593
11594 cds_ssr_protect(__func__);
11595 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11596 cds_ssr_unprotect(__func__);
11597
11598 return ret;
11599}
11600
11601/*
11602 * FUNCTION: __wlan_hdd_cfg80211_add_key
11603 * This function is used to initialize the key information
11604 */
11605static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11606 struct net_device *ndev,
11607 u8 key_index, bool pairwise,
11608 const u8 *mac_addr,
11609 struct key_params *params)
11610{
11611 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11612 tCsrRoamSetKey setKey;
11613 int status;
11614 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011615 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011616 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011617 hdd_context_t *pHddCtx;
11618 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11619
11620 ENTER();
11621
Anurag Chouhan6d760662016-02-20 16:05:43 +053011622 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011623 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011624 return -EINVAL;
11625 }
11626
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011627 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011628 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011629 return -EINVAL;
11630 }
11631
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011632 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011633 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11634 pAdapter->sessionId, params->key_len));
11635 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11636 status = wlan_hdd_validate_context(pHddCtx);
11637
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011638 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011639 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011640
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011641 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011642 hdd_device_mode_to_string(pAdapter->device_mode),
11643 pAdapter->device_mode);
11644
11645 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011646 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011647
11648 return -EINVAL;
11649 }
11650
11651 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011652 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011653
11654 return -EINVAL;
11655 }
11656
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011657 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658
11659 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011660 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011661 setKey.keyId = key_index;
11662 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011663 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664
11665 switch (params->cipher) {
11666 case WLAN_CIPHER_SUITE_WEP40:
11667 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11668 break;
11669
11670 case WLAN_CIPHER_SUITE_WEP104:
11671 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11672 break;
11673
11674 case WLAN_CIPHER_SUITE_TKIP:
11675 {
11676 u8 *pKey = &setKey.Key[0];
11677 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11678
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011679 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011680
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011681 /* Supplicant sends the 32bytes key in this order
11682 *
11683 * |--------------|----------|----------|
11684 * | Tk1 |TX-MIC | RX Mic |
11685 * |--------------|----------|----------|
11686 * <---16bytes---><--8bytes--><--8bytes-->
11687 *
11688 * Sme expects the 32 bytes key to be in the below order
11689 *
11690 * |--------------|----------|----------|
11691 * | Tk1 |RX-MIC | TX Mic |
11692 * |--------------|----------|----------|
11693 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011694 */
11695 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011696 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011697
11698 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011699 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011700
11701 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011702 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011703
11704 break;
11705 }
11706
11707 case WLAN_CIPHER_SUITE_CCMP:
11708 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11709 break;
11710
11711#ifdef FEATURE_WLAN_WAPI
11712 case WLAN_CIPHER_SUITE_SMS4:
11713 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011714 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011715 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11716 mac_addr, params->key,
11717 params->key_len);
11718 return 0;
11719 }
11720#endif
11721
11722#ifdef FEATURE_WLAN_ESE
11723 case WLAN_CIPHER_SUITE_KRK:
11724 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11725 break;
11726#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11727 case WLAN_CIPHER_SUITE_BTK:
11728 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11729 break;
11730#endif
11731#endif
11732
11733#ifdef WLAN_FEATURE_11W
11734 case WLAN_CIPHER_SUITE_AES_CMAC:
11735 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11736 break;
11737#endif
11738
11739 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011740 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011741 return -EOPNOTSUPP;
11742 }
11743
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011744 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011745
11746 if (!pairwise) {
11747 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011748 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011749 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011750 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011751 } else {
11752 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011753 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011754 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011755 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011756 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011757 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011758 /* if a key is already installed, block all subsequent ones */
11759 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011760 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011761 return 0;
11762 }
11763
11764 setKey.keyDirection = eSIR_TX_RX;
11765 /*Set the group key */
11766 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11767 pAdapter->sessionId, &setKey, &roamId);
11768
11769 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011770 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011771 return -EINVAL;
11772 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011773 /* Save the keys here and call sme_roam_set_key for setting
11774 * the PTK after peer joins the IBSS network
11775 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011776 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011777 &setKey, sizeof(tCsrRoamSetKey));
11778
11779 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11780 return status;
11781 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011782 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11783 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11785 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011786 status = wlansap_set_key_sta(
11787 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011788 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011789 hdd_err("wlansap_set_key_sta failed status: %d",
11790 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011791 }
11792 }
11793
11794 /* Save the key in ap ctx for use on START_BASS and restart */
11795 if (pairwise ||
11796 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11797 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011798 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011799 sizeof(tCsrRoamSetKey));
11800 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011801 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011802 sizeof(tCsrRoamSetKey));
11803
Krunal Sonib4326f22016-03-10 13:05:51 -080011804 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11805 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011806 hdd_wext_state_t *pWextState =
11807 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11808 hdd_station_ctx_t *pHddStaCtx =
11809 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11810
11811 if (!pairwise) {
11812 /* set group key */
11813 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011814 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011815 __func__, __LINE__);
11816 hdd_perform_roam_set_key_complete(pAdapter);
11817 }
11818 }
11819
11820 pWextState->roamProfile.Keys.KeyLength[key_index] =
11821 (u8) params->key_len;
11822
11823 pWextState->roamProfile.Keys.defaultIndex = key_index;
11824
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011825 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 KeyMaterial[key_index][0], params->key,
11827 params->key_len);
11828
11829 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11830
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011831 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011832 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11833 setKey.keyDirection);
11834
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011835 /* The supplicant may attempt to set the PTK once
11836 * pre-authentication is done. Save the key in the
11837 * UMAC and include it in the ADD BSS request
11838 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011839 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011840 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011841 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011842 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011843 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011844 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011845 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011846 return -EINVAL;
11847 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848
11849 /* issue set key request to SME */
11850 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11851 pAdapter->sessionId, &setKey, &roamId);
11852
11853 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011854 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011855 pHddStaCtx->roam_info.roamingState =
11856 HDD_ROAM_STATE_NONE;
11857 return -EINVAL;
11858 }
11859
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011860 /* in case of IBSS as there was no information
11861 * available about WEP keys during IBSS join, group
11862 * key intialized with NULL key, so re-initialize
11863 * group key with correct value
11864 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011865 if ((eCSR_BSS_TYPE_START_IBSS ==
11866 pWextState->roamProfile.BSSType)
11867 &&
11868 !((IW_AUTH_KEY_MGMT_802_1X ==
11869 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11870 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11871 pHddStaCtx->conn_info.authType)
11872 )
11873 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11874 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11875 )
11876 ) {
11877 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011878 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011879
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011880 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011881 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11882 setKey.keyDirection);
11883
11884 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11885 pAdapter->sessionId, &setKey,
11886 &roamId);
11887
11888 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011889 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011890 pHddStaCtx->roam_info.roamingState =
11891 HDD_ROAM_STATE_NONE;
11892 return -EINVAL;
11893 }
11894 }
11895 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011896 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011897 return 0;
11898}
11899
11900static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11901 struct net_device *ndev,
11902 u8 key_index, bool pairwise,
11903 const u8 *mac_addr,
11904 struct key_params *params)
11905{
11906 int ret;
11907 cds_ssr_protect(__func__);
11908 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11909 mac_addr, params);
11910 cds_ssr_unprotect(__func__);
11911
11912 return ret;
11913}
11914
11915/*
11916 * FUNCTION: __wlan_hdd_cfg80211_get_key
11917 * This function is used to get the key information
11918 */
11919static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11920 struct net_device *ndev,
11921 u8 key_index, bool pairwise,
11922 const u8 *mac_addr, void *cookie,
11923 void (*callback)(void *cookie,
11924 struct key_params *)
11925 )
11926{
11927 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11928 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11929 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11930 struct key_params params;
11931
11932 ENTER();
11933
Anurag Chouhan6d760662016-02-20 16:05:43 +053011934 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011935 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011936 return -EINVAL;
11937 }
11938
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011939 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011940 hdd_device_mode_to_string(pAdapter->device_mode),
11941 pAdapter->device_mode);
11942
11943 memset(&params, 0, sizeof(params));
11944
11945 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011946 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011947 return -EINVAL;
11948 }
11949
11950 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11951 case eCSR_ENCRYPT_TYPE_NONE:
11952 params.cipher = IW_AUTH_CIPHER_NONE;
11953 break;
11954
11955 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11956 case eCSR_ENCRYPT_TYPE_WEP40:
11957 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11958 break;
11959
11960 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11961 case eCSR_ENCRYPT_TYPE_WEP104:
11962 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11963 break;
11964
11965 case eCSR_ENCRYPT_TYPE_TKIP:
11966 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11967 break;
11968
11969 case eCSR_ENCRYPT_TYPE_AES:
11970 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11971 break;
11972
11973 default:
11974 params.cipher = IW_AUTH_CIPHER_NONE;
11975 break;
11976 }
11977
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011978 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011979 TRACE_CODE_HDD_CFG80211_GET_KEY,
11980 pAdapter->sessionId, params.cipher));
11981
11982 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11983 params.seq_len = 0;
11984 params.seq = NULL;
11985 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11986 callback(cookie, &params);
11987
11988 EXIT();
11989 return 0;
11990}
11991
11992static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11993 struct net_device *ndev,
11994 u8 key_index, bool pairwise,
11995 const u8 *mac_addr, void *cookie,
11996 void (*callback)(void *cookie,
11997 struct key_params *)
11998 )
11999{
12000 int ret;
12001
12002 cds_ssr_protect(__func__);
12003 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12004 mac_addr, cookie, callback);
12005 cds_ssr_unprotect(__func__);
12006
12007 return ret;
12008}
12009
12010/**
12011 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12012 * @wiphy: wiphy interface context
12013 * @ndev: pointer to net device
12014 * @key_index: Key index used in 802.11 frames
12015 * @unicast: true if it is unicast key
12016 * @multicast: true if it is multicast key
12017 *
12018 * This function is required for cfg80211_ops API.
12019 * It is used to delete the key information
12020 * Underlying hardware implementation does not have API to delete the
12021 * encryption key. It is automatically deleted when the peer is
12022 * removed. Hence this function currently does nothing.
12023 * Future implementation may interprete delete key operation to
12024 * replacing the key with a random junk value, effectively making it
12025 * useless.
12026 *
12027 * Return: status code, always 0.
12028 */
12029
12030static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12031 struct net_device *ndev,
12032 u8 key_index,
12033 bool pairwise, const u8 *mac_addr)
12034{
12035 EXIT();
12036 return 0;
12037}
12038
12039/**
12040 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12041 * @wiphy: Pointer to wiphy structure.
12042 * @dev: Pointer to net_device structure.
12043 * @key_index: key index
12044 * @pairwise: pairwise
12045 * @mac_addr: mac address
12046 *
12047 * This is the cfg80211 delete key handler function which invokes
12048 * the internal function @__wlan_hdd_cfg80211_del_key with
12049 * SSR protection.
12050 *
12051 * Return: 0 for success, error number on failure.
12052 */
12053static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12054 struct net_device *dev,
12055 u8 key_index,
12056 bool pairwise, const u8 *mac_addr)
12057{
12058 int ret;
12059
12060 cds_ssr_protect(__func__);
12061 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12062 pairwise, mac_addr);
12063 cds_ssr_unprotect(__func__);
12064
12065 return ret;
12066}
12067
12068/*
12069 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12070 * This function is used to set the default tx key index
12071 */
12072static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12073 struct net_device *ndev,
12074 u8 key_index,
12075 bool unicast, bool multicast)
12076{
12077 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12078 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12079 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12080 hdd_context_t *pHddCtx;
12081 int status;
12082
12083 ENTER();
12084
Anurag Chouhan6d760662016-02-20 16:05:43 +053012085 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012086 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012087 return -EINVAL;
12088 }
12089
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012090 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012091 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012092 return -EINVAL;
12093 }
12094
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012095 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012096 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12097 pAdapter->sessionId, key_index));
12098
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012099 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 hdd_device_mode_to_string(pAdapter->device_mode),
12101 pAdapter->device_mode, key_index);
12102
12103 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012104 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012105 return -EINVAL;
12106 }
12107
12108 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12109 status = wlan_hdd_validate_context(pHddCtx);
12110
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012111 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012112 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012113
Krunal Sonib4326f22016-03-10 13:05:51 -080012114 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12115 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012116 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12117 pHddStaCtx->conn_info.ucEncryptionType) &&
12118 (eCSR_ENCRYPT_TYPE_AES !=
12119 pHddStaCtx->conn_info.ucEncryptionType)) {
12120 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012121 * then update the default key index
12122 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123
12124 tCsrRoamSetKey setKey;
12125 uint32_t roamId = 0xFF;
12126 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12127
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012128 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012129
12130 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012131 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012132 setKey.keyId = key_index;
12133 setKey.keyLength = Keys->KeyLength[key_index];
12134
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012135 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012136 &Keys->KeyMaterial[key_index][0],
12137 Keys->KeyLength[key_index]);
12138
12139 setKey.keyDirection = eSIR_TX_RX;
12140
Anurag Chouhanc5548422016-02-24 18:33:27 +053012141 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012142 &pHddStaCtx->conn_info.bssId);
12143
12144 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12145 pWextState->roamProfile.EncryptionType.
12146 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012147 /* In the case of dynamic wep
12148 * supplicant hardcodes DWEP type to
12149 * eCSR_ENCRYPT_TYPE_WEP104 even
12150 * though ap is configured for WEP-40
12151 * encryption. In this canse the key
12152 * length is 5 but the encryption type
12153 * is 104 hence checking the key
12154 * lenght(5) and encryption type(104)
12155 * and switching encryption type to 40
12156 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012157 pWextState->roamProfile.EncryptionType.
12158 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12159 pWextState->roamProfile.mcEncryptionType.
12160 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12161 }
12162
12163 setKey.encType =
12164 pWextState->roamProfile.EncryptionType.
12165 encryptionType[0];
12166
12167 /* Issue set key request */
12168 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12169 pAdapter->sessionId, &setKey,
12170 &roamId);
12171
12172 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012173 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 status);
12175 return -EINVAL;
12176 }
12177 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012178 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012179 /* In SoftAp mode setting key direction for default mode */
12180 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12181 pWextState->roamProfile.EncryptionType.encryptionType[0])
12182 && (eCSR_ENCRYPT_TYPE_AES !=
12183 pWextState->roamProfile.EncryptionType.
12184 encryptionType[0])) {
12185 /* Saving key direction for default key index to TX default */
12186 hdd_ap_ctx_t *pAPCtx =
12187 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12188 pAPCtx->wepKey[key_index].keyDirection =
12189 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012190 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012191 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012192 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012193 }
12194 }
12195
12196 EXIT();
12197 return status;
12198}
12199
12200static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12201 struct net_device *ndev,
12202 u8 key_index,
12203 bool unicast, bool multicast)
12204{
12205 int ret;
12206 cds_ssr_protect(__func__);
12207 ret =
12208 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12209 multicast);
12210 cds_ssr_unprotect(__func__);
12211
12212 return ret;
12213}
12214
Abhishek Singhc9941602016-08-09 16:06:22 +053012215/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012216 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12217 * interface that BSS might have been lost.
12218 * @pAdapter: adaptor
12219 * @bssid: bssid which might have been lost
12220 *
12221 * Return: bss which is unlinked from kernel cache
12222 */
12223struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12224 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012225{
12226 struct net_device *dev = pAdapter->dev;
12227 struct wireless_dev *wdev = dev->ieee80211_ptr;
12228 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012229 struct cfg80211_bss *bss = NULL;
12230
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012231 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012232 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012233 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012234 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012235 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012236 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012237 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012238 cfg80211_unlink_bss(wiphy, bss);
12239 }
12240 return bss;
12241}
12242
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012243#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12244 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12245static struct cfg80211_bss *
12246wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12247 struct ieee80211_channel *chan,
12248 struct ieee80211_mgmt *mgmt,
12249 size_t frame_len,
12250 int rssi, gfp_t gfp,
12251 uint64_t boottime_ns)
12252{
12253 struct cfg80211_bss *bss_status = NULL;
12254 struct cfg80211_inform_bss data = {0};
12255
12256 data.chan = chan;
12257 data.boottime_ns = boottime_ns;
12258 data.signal = rssi;
12259 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12260 frame_len, gfp);
12261 return bss_status;
12262}
12263#else
12264static struct cfg80211_bss *
12265wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12266 struct ieee80211_channel *chan,
12267 struct ieee80211_mgmt *mgmt,
12268 size_t frame_len,
12269 int rssi, gfp_t gfp,
12270 uint64_t boottime_ns)
12271{
12272 struct cfg80211_bss *bss_status = NULL;
12273
12274 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12275 rssi, gfp);
12276 return bss_status;
12277}
12278#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012279
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012280/**
12281 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12282 * @pAdapter: Pointer to adapter
12283 * @bss_desc: Pointer to bss descriptor
12284 *
12285 * This function is used to inform the BSS details to nl80211 interface.
12286 *
12287 * Return: struct cfg80211_bss pointer
12288 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012289struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12290 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012291{
12292 /*
12293 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12294 * already exists in bss data base of cfg80211 for that particular BSS
12295 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12296 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12297 * As of now there is no possibility to get the mgmt(probe response)
12298 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12299 * and passing to cfg80211_inform_bss_frame.
12300 */
12301 struct net_device *dev = pAdapter->dev;
12302 struct wireless_dev *wdev = dev->ieee80211_ptr;
12303 struct wiphy *wiphy = wdev->wiphy;
12304 int chan_no = bss_desc->channelId;
12305#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12306 qcom_ie_age *qie_age = NULL;
12307 int ie_length =
12308 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12309#else
12310 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12311#endif
12312 const char *ie =
12313 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12314 unsigned int freq;
12315 struct ieee80211_channel *chan;
12316 struct ieee80211_mgmt *mgmt = NULL;
12317 struct cfg80211_bss *bss_status = NULL;
12318 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12319 int rssi = 0;
12320 hdd_context_t *pHddCtx;
12321 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012322 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012323 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324
12325 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12326 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012327 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012328 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012330 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012331 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012332 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012333 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 return NULL;
12335 }
12336
12337 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12338
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012340 * Instead it wants a monotonic increasing value
12341 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012342 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343 mgmt->u.probe_resp.timestamp =
12344 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012345
12346 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12347 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12348
12349#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12350 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12351 /* Assuming this is the last IE, copy at the end */
12352 ie_length -= sizeof(qcom_ie_age);
12353 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12354 qie_age->element_id = QCOM_VENDOR_IE_ID;
12355 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12356 qie_age->oui_1 = QCOM_OUI1;
12357 qie_age->oui_2 = QCOM_OUI2;
12358 qie_age->oui_3 = QCOM_OUI3;
12359 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012360 /*
12361 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12362 * all bss related timestamp is in units of ms. Due to this when scan
12363 * results are sent to lowi the scan age is high.To address this,
12364 * send age in units of 1/10 ms.
12365 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012366 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012367 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012368 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012369 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12370 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012371 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12372 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373#endif
12374
12375 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12376 if (bss_desc->fProbeRsp) {
12377 mgmt->frame_control |=
12378 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12379 } else {
12380 mgmt->frame_control |=
12381 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12382 }
12383
12384 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012385 (wiphy->bands[NL80211_BAND_2GHZ] != 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_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012389 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012390 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012391 freq =
12392 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012393 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012394 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012395 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012396 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012397 return NULL;
12398 }
12399
12400 chan = __ieee80211_get_channel(wiphy, freq);
12401 /* When the band is changed on the fly using the GUI, three things are done
12402 * 1. scan abort
12403 * 2. flush scan results from cache
12404 * 3. update the band with the new band user specified (refer to the
12405 * hdd_set_band_helper function) as part of the scan abort, message will be
12406 * queued to PE and we proceed with flushing and changinh the band.
12407 * PE will stop the scanning further and report back the results what ever
12408 * it had till now by calling the call back function.
12409 * if the time between update band and scandone call back is sufficient
12410 * enough the band change reflects in SME, SME validates the channels
12411 * and discards the channels correponding to previous band and calls back
12412 * with zero bss results. but if the time between band update and scan done
12413 * callback is very small then band change will not reflect in SME and SME
12414 * reports to HDD all the channels correponding to previous band.this is due
12415 * to race condition.but those channels are invalid to the new band and so
12416 * this function __ieee80211_get_channel will return NULL.Each time we
12417 * report scan result with this pointer null warning kernel trace is printed.
12418 * if the scan results contain large number of APs continuosly kernel
12419 * warning trace is printed and it will lead to apps watch dog bark.
12420 * So drop the bss and continue to next bss.
12421 */
12422 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012423 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12424 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012425 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012426 return NULL;
12427 }
12428
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012429 /* Based on .ini configuration, raw rssi can be reported for bss.
12430 * Raw rssi is typically used for estimating power.
12431 */
12432
12433 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12434 bss_desc->rssi;
12435
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012436 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012437 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012438
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012439 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012440 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012441 (int)(rssi / 100),
12442 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012443
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012444 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12445 frame_len, rssi,
12446 GFP_KERNEL,
12447 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012448 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012449 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012450 return bss_status;
12451}
12452
12453/**
12454 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12455 * @pAdapter: Pointer to adapter
12456 * @pRoamInfo: Pointer to roam info
12457 *
12458 * This function is used to update the BSS data base of CFG8011
12459 *
12460 * Return: struct cfg80211_bss pointer
12461 */
12462struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12463 tCsrRoamInfo *pRoamInfo)
12464{
12465 tCsrRoamConnectedProfile roamProfile;
12466 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12467 struct cfg80211_bss *bss = NULL;
12468
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012469 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12470 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12471
12472 if (NULL != roamProfile.pBssDesc) {
12473 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12474 roamProfile.pBssDesc);
12475
12476 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012477 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012478
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012479 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012481 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012482 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012483 return bss;
12484}
12485/**
12486 * wlan_hdd_cfg80211_update_bss() - update bss
12487 * @wiphy: Pointer to wiphy
12488 * @pAdapter: Pointer to adapter
12489 * @scan_time: scan request timestamp
12490 *
12491 * Return: zero if success, non-zero otherwise
12492 */
12493int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12494 hdd_adapter_t *pAdapter,
12495 uint32_t scan_time)
12496{
12497 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12498 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012499 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012500 tScanResultHandle pResult;
12501 struct cfg80211_bss *bss_status = NULL;
12502 hdd_context_t *pHddCtx;
12503 int ret;
12504
12505 ENTER();
12506
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012507 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12508 hdd_err("invalid session id: %d", pAdapter->sessionId);
12509 return -EINVAL;
12510 }
12511
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012512 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012513 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12514 NO_SESSION, pAdapter->sessionId));
12515
12516 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12517 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012518 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012519 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012520
12521 /* start getting scan results and populate cgf80211 BSS database */
12522 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12523
12524 /* no scan results */
12525 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012526 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012527 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528 }
12529
12530 pScanResult = sme_scan_result_get_first(hHal, pResult);
12531
12532 while (pScanResult) {
12533 /*
12534 * - cfg80211_inform_bss() is not updating ie field of bss
12535 * entry if entry already exists in bss data base of cfg80211
12536 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12537 * to update thebss entry instead of cfg80211_inform_bss,
12538 * But this call expects mgmt packet as input. As of now
12539 * there is no possibility to get the mgmt(probe response)
12540 * frame from PE, converting bss_desc to
12541 * ieee80211_mgmt(probe response) and passing to c
12542 * fg80211_inform_bss_frame.
12543 * - Update BSS only if beacon timestamp is later than
12544 * scan request timestamp.
12545 */
12546 if ((scan_time == 0) ||
12547 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012548 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012549 bss_status =
12550 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12551 &pScanResult->BssDescriptor);
12552
12553 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012554 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555 } else {
12556 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012557 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012558 bss_status);
12559 }
12560 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012561 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012562 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12563 }
12564 pScanResult = sme_scan_result_get_next(hHal, pResult);
12565 }
12566
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012567 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012568 /*
12569 * For SAP mode, scan is invoked by hostapd during SAP start
12570 * if hostapd is restarted, we need to flush previous scan
12571 * result so that it will reflect environment change
12572 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012573 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12575 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12576#endif
12577 )
12578 sme_scan_flush_result(hHal);
12579
12580 EXIT();
12581 return 0;
12582}
12583
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012584/**
12585 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12586 * @pAdapter: Pointer to adapter
12587 * @pRoamInfo: Pointer to roam info
12588 * @index: Index
12589 * @preauth: Preauth flag
12590 *
12591 * This function is used to notify the supplicant of a new PMKSA candidate.
12592 *
12593 * Return: 0 for success, non-zero for failure
12594 */
12595int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12596 tCsrRoamInfo *pRoamInfo,
12597 int index, bool preauth)
12598{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012599 struct net_device *dev = pAdapter->dev;
12600 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12601
12602 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012603 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012604
12605 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012606 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607 return -EINVAL;
12608 }
12609
12610 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012611 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12613 cfg80211_pmksa_candidate_notify(dev, index,
12614 pRoamInfo->bssid.bytes,
12615 preauth, GFP_KERNEL);
12616 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617 return 0;
12618}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012619
12620#ifdef FEATURE_WLAN_LFR_METRICS
12621/**
12622 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12623 * @pAdapter: Pointer to adapter
12624 * @pRoamInfo: Pointer to roam info
12625 *
12626 * 802.11r/LFR metrics reporting function to report preauth initiation
12627 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012628 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012629 */
12630#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012631QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012632 tCsrRoamInfo *pRoamInfo)
12633{
12634 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12635 union iwreq_data wrqu;
12636
12637 ENTER();
12638
12639 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012640 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012641 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012642 }
12643
12644 /* create the event */
12645 memset(&wrqu, 0, sizeof(wrqu));
12646 memset(metrics_notification, 0, sizeof(metrics_notification));
12647
12648 wrqu.data.pointer = metrics_notification;
12649 wrqu.data.length = scnprintf(metrics_notification,
12650 sizeof(metrics_notification),
12651 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12652 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12653
12654 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12655 metrics_notification);
12656
12657 EXIT();
12658
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012659 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012660}
12661
12662/**
12663 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12664 * @pAdapter: Pointer to adapter
12665 * @pRoamInfo: Pointer to roam info
12666 * @preauth_status: Preauth status
12667 *
12668 * 802.11r/LFR metrics reporting function to report handover initiation
12669 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012670 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012672QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012673wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12674 tCsrRoamInfo *pRoamInfo,
12675 bool preauth_status)
12676{
12677 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12678 union iwreq_data wrqu;
12679
12680 ENTER();
12681
12682 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012683 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012684 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012685 }
12686
12687 /* create the event */
12688 memset(&wrqu, 0, sizeof(wrqu));
12689 memset(metrics_notification, 0, sizeof(metrics_notification));
12690
12691 scnprintf(metrics_notification, sizeof(metrics_notification),
12692 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12693 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12694
12695 if (1 == preauth_status)
12696 strlcat(metrics_notification, " true",
12697 sizeof(metrics_notification));
12698 else
12699 strlcat(metrics_notification, " false",
12700 sizeof(metrics_notification));
12701
12702 wrqu.data.pointer = metrics_notification;
12703 wrqu.data.length = strlen(metrics_notification);
12704
12705 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12706 metrics_notification);
12707
12708 EXIT();
12709
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012710 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012711}
12712
12713/**
12714 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12715 * @pAdapter: Pointer to adapter
12716 * @pRoamInfo: Pointer to roam info
12717 *
12718 * 802.11r/LFR metrics reporting function to report handover initiation
12719 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012720 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012721 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012722QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012723 tCsrRoamInfo *pRoamInfo)
12724{
12725 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12726 union iwreq_data wrqu;
12727
12728 ENTER();
12729
12730 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012731 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012732 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012733 }
12734
12735 /* create the event */
12736 memset(&wrqu, 0, sizeof(wrqu));
12737 memset(metrics_notification, 0, sizeof(metrics_notification));
12738
12739 wrqu.data.pointer = metrics_notification;
12740 wrqu.data.length = scnprintf(metrics_notification,
12741 sizeof(metrics_notification),
12742 "QCOM: LFR_PREAUTH_HANDOVER "
12743 MAC_ADDRESS_STR,
12744 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12745
12746 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12747 metrics_notification);
12748
12749 EXIT();
12750
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012751 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012752}
12753#endif
12754
12755/**
12756 * hdd_select_cbmode() - select channel bonding mode
12757 * @pAdapter: Pointer to adapter
12758 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012759 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760 *
12761 * Return: none
12762 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012763void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080012764 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012765{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012766 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012767 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012768 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012769
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012770 /*
12771 * CDS api expects secondary channel for calculating
12772 * the channel params
12773 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012774 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012775 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12776 if (operationChannel >= 1 && operationChannel <= 5)
12777 sec_ch = operationChannel + 4;
12778 else if (operationChannel >= 6 && operationChannel <= 13)
12779 sec_ch = operationChannel - 4;
12780 }
12781
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012783 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012784
12785 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012786 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012787 uint8_t iniDot11Mode =
12788 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12789
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012790 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012791 switch (iniDot11Mode) {
12792 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012793 case eHDD_DOT11_MODE_11ax:
12794 case eHDD_DOT11_MODE_11ax_ONLY:
12795 if (sme_is_feature_supported_by_fw(DOT11AX))
12796 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12797 else if (sme_is_feature_supported_by_fw(DOT11AC))
12798 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12799 else
12800 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12801 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012802 case eHDD_DOT11_MODE_11ac:
12803 case eHDD_DOT11_MODE_11ac_ONLY:
12804 if (sme_is_feature_supported_by_fw(DOT11AC))
12805 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12806 else
12807 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12808 break;
12809 case eHDD_DOT11_MODE_11n:
12810 case eHDD_DOT11_MODE_11n_ONLY:
12811 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12812 break;
12813 default:
12814 hdd_dot11_mode = iniDot11Mode;
12815 break;
12816 }
12817 ch_info->channel_width = ch_params->ch_width;
12818 ch_info->phy_mode =
12819 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012820 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012821 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012822 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012823 ch_info->channel_width, ch_info->phy_mode,
12824 ch_info->channel);
12825 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012826}
12827
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012828/**
12829 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12830 * @adapter: STA adapter
12831 * @roam_profile: STA roam profile
12832 *
12833 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12834 *
12835 * Return: false if sta-sap conc is not allowed, else return true
12836 */
12837static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12838 tCsrRoamProfile *roam_profile)
12839{
12840 hdd_context_t *hdd_ctx;
12841 hdd_adapter_t *ap_adapter;
12842 hdd_ap_ctx_t *hdd_ap_ctx;
12843 hdd_hostapd_state_t *hostapd_state;
12844 uint8_t channel = 0;
12845 QDF_STATUS status;
12846
12847 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12848 if (!hdd_ctx) {
12849 hdd_err("HDD context is NULL");
12850 return true;
12851 }
12852
12853 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12854 /* probably no sap running, no handling required */
12855 if (ap_adapter == NULL)
12856 return true;
12857
12858 /*
12859 * sap is not in started state, so it is fine to go ahead with sta.
12860 * if sap is currently doing CAC then don't allow sta to go further.
12861 */
12862 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12863 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12864 return true;
12865
12866 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12867 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12868 return false;
12869 }
12870
12871 /*
12872 * log and return error, if we allow STA to go through, we don't
12873 * know what is going to happen better stop sta connection
12874 */
12875 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12876 if (NULL == hdd_ap_ctx) {
12877 hdd_err("AP context not found");
12878 return false;
12879 }
12880
12881 /* sap is on non-dfs channel, nothing to handle */
12882 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012883 hdd_debug("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012884 return true;
12885 }
12886 /*
12887 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012888 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012889 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012890 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012891 roam_profile, &channel);
12892
Nitesh Shah59774522016-09-16 15:14:21 +053012893 /*
12894 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12895 * channels for roaming case.
12896 */
12897 if (CDS_IS_CHANNEL_24GHZ(channel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012898 hdd_debug("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012899 return true;
12900 }
12901
12902 /*
12903 * If channel is 0 or DFS then better to call pcl and find out the
12904 * best channel. If channel is non-dfs 5 GHz then better move SAP
12905 * to STA's channel to make scc, so we have room for 3port MCC
12906 * scenario.
12907 */
12908 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012909 channel = policy_mgr_get_nondfs_preferred_channel(
12910 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012911
12912 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12913 qdf_event_reset(&hostapd_state->qdf_event);
12914 status = wlansap_set_channel_change_with_csa(
12915 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12916 hdd_ap_ctx->sapConfig.ch_width_orig);
12917
12918 if (QDF_STATUS_SUCCESS != status) {
12919 hdd_err("Set channel with CSA IE failed, can't allow STA");
12920 return false;
12921 }
12922
12923 /*
12924 * wait here for SAP to finish the channel switch. When channel
12925 * switch happens, SAP sends few beacons with CSA_IE. After
12926 * successfully Transmission of those beacons, it will move its
12927 * state from started to disconnected and move to new channel.
12928 * once it moves to new channel, sap again moves its state
12929 * machine from disconnected to started and set this event.
12930 * wait for 10 secs to finish this.
12931 */
12932 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12933 if (!QDF_IS_STATUS_SUCCESS(status)) {
12934 hdd_err("wait for qdf_event failed, STA not allowed!!");
12935 return false;
12936 }
12937
12938 return true;
12939}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012940
Abhishek Singhcfb44482017-03-10 12:42:37 +053012941#ifdef WLAN_FEATURE_11W
12942/**
12943 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12944 * @roam_profile: pointer to roam profile
12945 *
12946 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12947 * or pmf=2 is an explicit configuration in the supplicant
12948 * configuration, drop the connection request.
12949 *
12950 * Return: 0 if check result is valid, otherwise return error code
12951 */
12952static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12953{
12954 if (roam_profile->MFPEnabled &&
12955 !(roam_profile->MFPRequired ||
12956 roam_profile->MFPCapable)) {
12957 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12958 roam_profile->MFPEnabled,
12959 roam_profile->MFPRequired,
12960 roam_profile->MFPCapable);
12961 return -EINVAL;
12962 }
12963 return 0;
12964}
12965#else
12966static inline
12967int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12968{
12969 return 0;
12970}
12971#endif
12972
Krunal Soni31949422016-07-29 17:17:53 -070012973/**
12974 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012975 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012976 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012977 * @ssid_len: Length of ssid
12978 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012979 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012980 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012981 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012982 *
12983 * This function is used to start the association process
12984 *
12985 * Return: 0 for success, non-zero for failure
12986 */
Krunal Soni31949422016-07-29 17:17:53 -070012987static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012988 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012989 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012990 u8 operatingChannel,
12991 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012992{
12993 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012994 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012995 hdd_wext_state_t *pWextState;
12996 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012997 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998 uint32_t roamId;
12999 tCsrRoamProfile *pRoamProfile;
13000 eCsrAuthType RSNAuthType;
13001 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013002 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013003
13004 ENTER();
13005
13006 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13007 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013008 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013009
13010 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013011 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013012 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013013
13014 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013015 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013016 status = -EINVAL;
13017 goto ret_status;
13018 }
13019
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013020 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013021 hdd_err("Connection refused: conn in progress");
13022 status = -EINVAL;
13023 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013024 }
13025
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013026 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013027 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13028
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013029 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013030 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13031 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013032
13033 if (pRoamProfile) {
13034 hdd_station_ctx_t *pHddStaCtx;
13035 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13036
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013037 /* Restart the opportunistic timer
13038 *
13039 * If hw_mode_change_in_progress is true, then wait
13040 * till firmware sends the callback for hw_mode change.
13041 *
13042 * Else set connect_in_progress as true and proceed.
13043 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013044 policy_mgr_restart_opportunistic_timer(
13045 pHddCtx->hdd_psoc, false);
13046 if (policy_mgr_is_hw_mode_change_in_progress(
13047 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013048 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013049 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013050 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013051 hdd_err("qdf wait for event failed!!");
13052 status = -EINVAL;
13053 goto ret_status;
13054 }
13055 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013056 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013057
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013058 if (HDD_WMM_USER_MODE_NO_QOS ==
13059 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13060 /*QoS not enabled in cfg file */
13061 pRoamProfile->uapsd_mask = 0;
13062 } else {
13063 /*QoS enabled, update uapsd mask from cfg file */
13064 pRoamProfile->uapsd_mask =
13065 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13066 }
13067
13068 pRoamProfile->SSIDs.numOfSSIDs = 1;
13069 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013070 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013071 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013072 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013073 ssid, ssid_len);
13074
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013075 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013076 /* cleanup bssid hint */
13077 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13078 QDF_MAC_ADDR_SIZE);
13079 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13080 QDF_MAC_ADDR_SIZE);
13081
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013082 if (bssid) {
13083 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013084 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013085 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013086 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013087 /*
13088 * Save BSSID in seperate variable as
13089 * pRoamProfile's BSSID is getting zeroed out in the
13090 * association process. In case of join failure
13091 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013092 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013093 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013094 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013095 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013096 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013097 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13098 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013099 /*
13100 * Save BSSID in a separate variable as
13101 * pRoamProfile's BSSID is getting zeroed out in the
13102 * association process. In case of join failure
13103 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013104 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013105 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013106 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013107 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013108 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109 }
13110
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013111 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013112 pRoamProfile->SSIDs.SSIDList->SSID.length,
13113 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13114 operatingChannel);
13115
13116 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13117 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013119 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13120 }
13121#ifdef FEATURE_WLAN_WAPI
13122 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013123 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013124 switch (pAdapter->wapi_info.wapiAuthMode) {
13125 case WAPI_AUTH_MODE_PSK:
13126 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013127 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013128 pAdapter->wapi_info.wapiAuthMode);
13129 pRoamProfile->AuthType.authType[0] =
13130 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13131 break;
13132 }
13133 case WAPI_AUTH_MODE_CERT:
13134 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013135 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013136 pAdapter->wapi_info.wapiAuthMode);
13137 pRoamProfile->AuthType.authType[0] =
13138 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13139 break;
13140 }
13141 } /* End of switch */
13142 if (pAdapter->wapi_info.wapiAuthMode ==
13143 WAPI_AUTH_MODE_PSK
13144 || pAdapter->wapi_info.wapiAuthMode ==
13145 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013146 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013147 pRoamProfile->AuthType.numEntries = 1;
13148 pRoamProfile->EncryptionType.numEntries = 1;
13149 pRoamProfile->EncryptionType.encryptionType[0] =
13150 eCSR_ENCRYPT_TYPE_WPI;
13151 pRoamProfile->mcEncryptionType.numEntries = 1;
13152 pRoamProfile->mcEncryptionType.
13153 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13154 }
13155 }
Krunal Soni31949422016-07-29 17:17:53 -070013156#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013157 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013158 pRoamProfile->csrPersona = pAdapter->device_mode;
13159
13160 if (operatingChannel) {
13161 pRoamProfile->ChannelInfo.ChannelList =
13162 &operatingChannel;
13163 pRoamProfile->ChannelInfo.numOfChannels = 1;
13164 } else {
13165 pRoamProfile->ChannelInfo.ChannelList = NULL;
13166 pRoamProfile->ChannelInfo.numOfChannels = 0;
13167 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013168 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013169 && operatingChannel) {
13170 /*
13171 * Need to post the IBSS power save parameters
13172 * to WMA. WMA will configure this parameters
13173 * to firmware if power save is enabled by the
13174 * firmware.
13175 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013176 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013177
Abhishek Singh471652b2017-04-14 12:28:32 +053013178 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013179 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013180 status = -EINVAL;
13181 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013182 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013183 pRoamProfile->ch_params.ch_width =
13184 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013185 /*
13186 * In IBSS mode while operating in 2.4 GHz,
13187 * the device supports only 20 MHz.
13188 */
13189 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13190 pRoamProfile->ch_params.ch_width =
13191 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013192 hdd_select_cbmode(pAdapter, operatingChannel,
13193 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194 }
13195
Abhishek Singhcfb44482017-03-10 12:42:37 +053013196 if (wlan_hdd_cfg80211_check_pmf_valid(
13197 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013198 status = -EINVAL;
13199 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013200 }
13201
Krunal Soni31949422016-07-29 17:17:53 -070013202 /*
13203 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013205 * enhancements, the supplicant is not issuing the scan command
13206 * now. So the unicast frames which are sent from the host are
13207 * not having the additional IEs. If it is P2P CLIENT and there
13208 * is no additional IE present in roamProfile, then use the
13209 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013210 */
13211
Krunal Sonib4326f22016-03-10 13:05:51 -080013212 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013213 (!pRoamProfile->pAddIEScan)) {
13214 pRoamProfile->pAddIEScan =
13215 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13216 pRoamProfile->nAddIEScanLength =
13217 pAdapter->scan_info.scanAddIE.length;
13218 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013219
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013220 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13221 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013222 pRoamProfile))) {
13223 hdd_err("sap-sta conc will fail, can't allow sta");
13224 hdd_conn_set_connection_state(pAdapter,
13225 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013226 status = -ENOMEM;
13227 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013228 }
13229
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013230 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231 if (!sme_config) {
13232 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013233 hdd_conn_set_connection_state(pAdapter,
13234 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013235 status = -ENOMEM;
13236 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013237 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013238 sme_get_config_param(pHddCtx->hHal, sme_config);
13239 /* These values are not sessionized. So, any change in these SME
13240 * configs on an older or parallel interface will affect the
13241 * cb mode. So, restoring the default INI params before starting
13242 * interfaces such as sta, cli etc.,
13243 */
13244 sme_config->csrConfig.channelBondingMode5GHz =
13245 pHddCtx->config->nChannelBondingMode5GHz;
13246 sme_config->csrConfig.channelBondingMode24GHz =
13247 pHddCtx->config->nChannelBondingMode24GHz;
13248 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013249 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013250 /*
13251 * Change conn_state to connecting before sme_roam_connect(),
13252 * because sme_roam_connect() has a direct path to call
13253 * hdd_sme_roam_callback(), which will change the conn_state
13254 * If direct path, conn_state will be accordingly changed to
13255 * NotConnected or Associated by either
13256 * hdd_association_completion_handler() or
13257 * hdd_dis_connect_handler() in sme_RoamCallback()if
13258 * sme_RomConnect is to be queued,
13259 * Connecting state will remain until it is completed.
13260 *
13261 * If connection state is not changed, connection state will
13262 * remain in eConnectionState_NotConnected state.
13263 * In hdd_association_completion_handler, "hddDisconInProgress"
13264 * is set to true if conn state is
13265 * eConnectionState_NotConnected.
13266 * If "hddDisconInProgress" is set to true then cfg80211 layer
13267 * is not informed of connect result indication which
13268 * is an issue.
13269 */
13270 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013271 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013272 hdd_conn_set_connection_state(pAdapter,
13273 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274
Komal Seelama89be8d2016-09-29 11:09:26 +053013275 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13276 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013277 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013278 pAdapter->sessionId, pRoamProfile,
13279 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013280 if (QDF_IS_STATUS_ERROR(qdf_status))
13281 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282
Rajeev Kumard31e1542017-01-13 14:37:42 -080013283 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013284 (QDF_STA_MODE == pAdapter->device_mode ||
13285 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013286 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013287 "qdf_status %d. -> NotConnected",
13288 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013289 /* change back to NotAssociated */
13290 hdd_conn_set_connection_state(pAdapter,
13291 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013292 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13293 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013294 }
13295
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013296 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013297 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013298
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013299 pRoamProfile->ChannelInfo.ChannelList = NULL;
13300 pRoamProfile->ChannelInfo.numOfChannels = 0;
13301
Nitesh Shah044fd672016-10-13 18:53:25 +053013302 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013303 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13304 && !policy_mgr_is_hw_dbs_2x2_capable(
13305 pHddCtx->hdd_psoc)) {
13306 policy_mgr_get_channel_from_scan_result(
13307 pHddCtx->hdd_psoc,
13308 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013309 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013310 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013311 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13312 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013313 }
13314
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013315 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013316 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013317 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013318 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013319 goto ret_status;
13320
13321conn_failure:
13322 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013323 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013324
13325ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013326 EXIT();
13327 return status;
13328}
13329
13330/**
13331 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13332 * @pAdapter: Pointer to adapter
13333 * @auth_type: Auth type
13334 *
13335 * This function is used to set the authentication type (OPEN/SHARED).
13336 *
13337 * Return: 0 for success, non-zero for failure
13338 */
13339static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13340 enum nl80211_auth_type auth_type)
13341{
13342 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13343 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13344
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013345 /*set authentication type */
13346 switch (auth_type) {
13347 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013348 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013349 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13350 break;
13351
13352 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013353 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013354 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013355 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13356 break;
13357
13358 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013359 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013360 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13361 break;
13362#ifdef FEATURE_WLAN_ESE
13363 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013364 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013365 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13366 break;
13367#endif
13368
13369 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013370 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013371 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13372 return -EINVAL;
13373 }
13374
13375 pWextState->roamProfile.AuthType.authType[0] =
13376 pHddStaCtx->conn_info.authType;
13377 return 0;
13378}
13379
13380/**
13381 * wlan_hdd_set_akm_suite() - set key management type
13382 * @pAdapter: Pointer to adapter
13383 * @key_mgmt: Key management type
13384 *
13385 * This function is used to set the key mgmt type(PSK/8021x).
13386 *
13387 * Return: 0 for success, non-zero for failure
13388 */
13389static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13390{
13391 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13392
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013393#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013394#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013395#endif
13396#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013397#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013398#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013399 /*set key mgmt type */
13400 switch (key_mgmt) {
13401 case WLAN_AKM_SUITE_PSK:
13402 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013403 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013404 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013405 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13406 break;
13407
13408 case WLAN_AKM_SUITE_8021X_SHA256:
13409 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013410 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013411 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013412 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13413 break;
13414#ifdef FEATURE_WLAN_ESE
13415#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13416#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13417 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013418 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013419 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13420 break;
13421#endif
13422#ifndef WLAN_AKM_SUITE_OSEN
13423#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13424#endif
13425 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013426 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013427 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13428 break;
13429
13430 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013431 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013432 return -EINVAL;
13433
13434 }
13435 return 0;
13436}
13437
13438/**
13439 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13440 * @pAdapter: Pointer to adapter
13441 * @cipher: Cipher type
13442 * @ucast: Unicast flag
13443 *
13444 * This function is used to set the encryption type
13445 * (NONE/WEP40/WEP104/TKIP/CCMP).
13446 *
13447 * Return: 0 for success, non-zero for failure
13448 */
13449static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13450 u32 cipher, bool ucast)
13451{
13452 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13453 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13454 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13455
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013456 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013457 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013458 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13459 } else {
13460
13461 /*set encryption method */
13462 switch (cipher) {
13463 case IW_AUTH_CIPHER_NONE:
13464 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13465 break;
13466
13467 case WLAN_CIPHER_SUITE_WEP40:
13468 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13469 break;
13470
13471 case WLAN_CIPHER_SUITE_WEP104:
13472 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13473 break;
13474
13475 case WLAN_CIPHER_SUITE_TKIP:
13476 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13477 break;
13478
13479 case WLAN_CIPHER_SUITE_CCMP:
13480 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13481 break;
13482#ifdef FEATURE_WLAN_WAPI
13483 case WLAN_CIPHER_SUITE_SMS4:
13484 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13485 break;
13486#endif
13487
13488#ifdef FEATURE_WLAN_ESE
13489 case WLAN_CIPHER_SUITE_KRK:
13490 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13491 break;
13492#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13493 case WLAN_CIPHER_SUITE_BTK:
13494 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13495 break;
13496#endif
13497#endif
13498 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013499 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013500 return -EOPNOTSUPP;
13501 }
13502 }
13503
13504 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013505 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013506 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13507 pWextState->roamProfile.EncryptionType.numEntries = 1;
13508 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13509 encryptionType;
13510 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013511 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013512 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13513 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13514 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13515 encryptionType;
13516 }
13517
13518 return 0;
13519}
13520
13521/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013522 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13523 * @wext_state: Pointer to wext state
13524 * @gen_ie: Pointer to IE data
13525 * @len: length of IE data
13526 *
13527 * Return: 0 for success, non-zero for failure
13528 */
13529static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13530 const uint8_t *gen_ie, uint16_t len)
13531{
13532 uint16_t cur_add_ie_len =
13533 wext_state->assocAddIE.length;
13534
13535 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13536 (wext_state->assocAddIE.length + len)) {
13537 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13538 QDF_ASSERT(0);
13539 return -ENOMEM;
13540 }
13541 memcpy(wext_state->assocAddIE.addIEdata +
13542 cur_add_ie_len, gen_ie, len);
13543 wext_state->assocAddIE.length += len;
13544
13545 wext_state->roamProfile.pAddIEAssoc =
13546 wext_state->assocAddIE.addIEdata;
13547 wext_state->roamProfile.nAddIEAssocLength =
13548 wext_state->assocAddIE.length;
13549 return 0;
13550}
13551
13552/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013553 * wlan_hdd_cfg80211_set_ie() - set IEs
13554 * @pAdapter: Pointer to adapter
13555 * @ie: Pointer ot ie
13556 * @ie: IE length
13557 *
13558 * Return: 0 for success, non-zero for failure
13559 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013560static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013561 size_t ie_len)
13562{
13563 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13564 const uint8_t *genie = ie;
13565 uint16_t remLen = ie_len;
13566#ifdef FEATURE_WLAN_WAPI
13567 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13568 u16 *tmp;
13569 uint16_t akmsuiteCount;
13570 int *akmlist;
13571#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013572 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013573
13574 /* clear previous assocAddIE */
13575 pWextState->assocAddIE.length = 0;
13576 pWextState->roamProfile.bWPSAssociation = false;
13577 pWextState->roamProfile.bOSENAssociation = false;
13578
13579 while (remLen >= 2) {
13580 uint16_t eLen = 0;
13581 uint8_t elementId;
13582 elementId = *genie++;
13583 eLen = *genie++;
13584 remLen -= 2;
13585
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013586 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013587
13588 switch (elementId) {
13589 case DOT11F_EID_WPA:
13590 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 -070013591 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013592 return -EINVAL;
13593 } else if (0 ==
13594 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13595 uint16_t curAddIELen =
13596 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013597 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013598
13599 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13600 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013601 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013602 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013603 return -ENOMEM;
13604 }
13605 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13606 memcpy(pWextState->assocAddIE.addIEdata +
13607 curAddIELen, genie - 2, eLen + 2);
13608 pWextState->assocAddIE.length += eLen + 2;
13609
13610 pWextState->roamProfile.bWPSAssociation = true;
13611 pWextState->roamProfile.pAddIEAssoc =
13612 pWextState->assocAddIE.addIEdata;
13613 pWextState->roamProfile.nAddIEAssocLength =
13614 pWextState->assocAddIE.length;
13615 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013616 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617 memset(pWextState->WPARSNIE, 0,
13618 MAX_WPA_RSN_IE_LEN);
13619 memcpy(pWextState->WPARSNIE, genie - 2,
13620 (eLen + 2));
13621 pWextState->roamProfile.pWPAReqIE =
13622 pWextState->WPARSNIE;
13623 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13624 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13625 P2P_OUI_TYPE_SIZE))) {
13626 uint16_t curAddIELen =
13627 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013628 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013629
13630 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13631 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013632 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013633 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013634 return -ENOMEM;
13635 }
13636 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13637 memcpy(pWextState->assocAddIE.addIEdata +
13638 curAddIELen, genie - 2, eLen + 2);
13639 pWextState->assocAddIE.length += eLen + 2;
13640
13641 pWextState->roamProfile.pAddIEAssoc =
13642 pWextState->assocAddIE.addIEdata;
13643 pWextState->roamProfile.nAddIEAssocLength =
13644 pWextState->assocAddIE.length;
13645 }
13646#ifdef WLAN_FEATURE_WFD
13647 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13648 WFD_OUI_TYPE_SIZE)) &&
13649 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013650 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013651 pAdapter->device_mode)) {
13652 uint16_t curAddIELen =
13653 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013654 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013655
13656 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13657 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013658 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013659 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 return -ENOMEM;
13661 }
13662 /* WFD IE is saved to Additional IE ; it should
13663 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013664 * WFD IE
13665 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013666 memcpy(pWextState->assocAddIE.addIEdata +
13667 curAddIELen, genie - 2, eLen + 2);
13668 pWextState->assocAddIE.length += eLen + 2;
13669
13670 pWextState->roamProfile.pAddIEAssoc =
13671 pWextState->assocAddIE.addIEdata;
13672 pWextState->roamProfile.nAddIEAssocLength =
13673 pWextState->assocAddIE.length;
13674 }
13675#endif
13676 /* Appending HS 2.0 Indication Element in Assiciation Request */
13677 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13678 HS20_OUI_TYPE_SIZE))) {
13679 uint16_t curAddIELen =
13680 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013681 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013682
13683 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13684 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013685 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013686 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013687 return -ENOMEM;
13688 }
13689 memcpy(pWextState->assocAddIE.addIEdata +
13690 curAddIELen, genie - 2, eLen + 2);
13691 pWextState->assocAddIE.length += eLen + 2;
13692
13693 pWextState->roamProfile.pAddIEAssoc =
13694 pWextState->assocAddIE.addIEdata;
13695 pWextState->roamProfile.nAddIEAssocLength =
13696 pWextState->assocAddIE.length;
13697 }
13698 /* Appending OSEN Information Element in Assiciation Request */
13699 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13700 OSEN_OUI_TYPE_SIZE))) {
13701 uint16_t curAddIELen =
13702 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013703 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013704
13705 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13706 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013707 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013708 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013709 return -ENOMEM;
13710 }
13711 memcpy(pWextState->assocAddIE.addIEdata +
13712 curAddIELen, genie - 2, eLen + 2);
13713 pWextState->assocAddIE.length += eLen + 2;
13714
13715 pWextState->roamProfile.bOSENAssociation = true;
13716 pWextState->roamProfile.pAddIEAssoc =
13717 pWextState->assocAddIE.addIEdata;
13718 pWextState->roamProfile.nAddIEAssocLength =
13719 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013720 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13721 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013722 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013723 status = wlan_hdd_add_assoc_ie(pWextState,
13724 genie - 2, eLen + 2);
13725 if (status)
13726 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013727 } else {
13728 uint16_t add_ie_len =
13729 pWextState->assocAddIE.length;
13730
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013731 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013732
13733 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13734 (pWextState->assocAddIE.length + eLen)) {
13735 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013736 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013737 return -ENOMEM;
13738 }
13739
13740 memcpy(pWextState->assocAddIE.addIEdata +
13741 add_ie_len, genie - 2, eLen + 2);
13742 pWextState->assocAddIE.length += eLen + 2;
13743
13744 pWextState->roamProfile.pAddIEAssoc =
13745 pWextState->assocAddIE.addIEdata;
13746 pWextState->roamProfile.nAddIEAssocLength =
13747 pWextState->assocAddIE.length;
13748 }
13749 break;
13750 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013751 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013752 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13753 memcpy(pWextState->WPARSNIE, genie - 2,
13754 (eLen + 2));
13755 pWextState->roamProfile.pRSNReqIE =
13756 pWextState->WPARSNIE;
13757 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13758 break;
13759 /*
13760 * Appending Extended Capabilities with Interworking bit set
13761 * in Assoc Req.
13762 *
13763 * In assoc req this EXT Cap will only be taken into account if
13764 * interworkingService bit is set to 1. Currently
13765 * driver is only interested in interworkingService capability
13766 * from supplicant. If in future any other EXT Cap info is
13767 * required from supplicat, it needs to be handled while
13768 * sending Assoc Req in LIM.
13769 */
13770 case DOT11F_EID_EXTCAP:
13771 {
13772 uint16_t curAddIELen =
13773 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013774 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013775
13776 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13777 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013778 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013779 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013780 return -ENOMEM;
13781 }
13782 memcpy(pWextState->assocAddIE.addIEdata +
13783 curAddIELen, genie - 2, eLen + 2);
13784 pWextState->assocAddIE.length += eLen + 2;
13785
13786 pWextState->roamProfile.pAddIEAssoc =
13787 pWextState->assocAddIE.addIEdata;
13788 pWextState->roamProfile.nAddIEAssocLength =
13789 pWextState->assocAddIE.length;
13790 break;
13791 }
13792#ifdef FEATURE_WLAN_WAPI
13793 case WLAN_EID_WAPI:
13794 /* Setting WAPI Mode to ON=1 */
13795 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013796 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013797 tmp = (u16 *) ie;
13798 tmp = tmp + 2; /* Skip element Id and Len, Version */
13799 akmsuiteCount = WPA_GET_LE16(tmp);
13800 tmp = tmp + 1;
13801 akmlist = (int *)(tmp);
13802 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13803 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13804 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013805 hdd_err("Invalid akmSuite count: %u",
13806 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013807 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013808 return -EINVAL;
13809 }
13810
13811 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013812 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013813 pAdapter->wapi_info.wapiAuthMode =
13814 WAPI_AUTH_MODE_PSK;
13815 }
13816 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013817 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013818 pAdapter->wapi_info.wapiAuthMode =
13819 WAPI_AUTH_MODE_CERT;
13820 }
13821 break;
13822#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013823 case DOT11F_EID_SUPPOPERATINGCLASSES:
13824 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013825 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013826 status = wlan_hdd_add_assoc_ie(pWextState,
13827 genie - 2, eLen + 2);
13828 if (status)
13829 return status;
13830 break;
13831 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013832 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013833 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013834 /* when Unknown IE is received we break
13835 * and continue to the next IE in the buffer
13836 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013837 break;
13838 }
13839 genie += eLen;
13840 remLen -= eLen;
13841 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013842 return 0;
13843}
13844
13845/**
13846 * hdd_is_wpaie_present() - check for WPA ie
13847 * @ie: Pointer to ie
13848 * @ie_len: Ie length
13849 *
13850 * Parse the received IE to find the WPA IE
13851 *
13852 * Return: true if wpa ie is found else false
13853 */
13854static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13855{
13856 uint8_t eLen = 0;
13857 uint16_t remLen = ie_len;
13858 uint8_t elementId = 0;
13859
13860 while (remLen >= 2) {
13861 elementId = *ie++;
13862 eLen = *ie++;
13863 remLen -= 2;
13864 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013865 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013866 return false;
13867 }
13868 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13869 /* OUI - 0x00 0X50 0XF2
13870 * WPA Information Element - 0x01
13871 * WPA version - 0x01
13872 */
13873 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13874 return true;
13875 }
13876 ie += eLen;
13877 remLen -= eLen;
13878 }
13879 return false;
13880}
13881
13882/**
13883 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13884 * @pAdapter: Pointer to adapter
13885 * @req: Pointer to security parameters
13886 *
13887 * Return: 0 for success, non-zero for failure
13888 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013889static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13890 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013891{
13892 int status = 0;
13893 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13894 ENTER();
13895
13896 /*set wpa version */
13897 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13898
13899 if (req->crypto.wpa_versions) {
13900 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13901 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13902 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13903 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13904 }
13905 }
13906
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013907 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013908
13909 /*set authentication type */
13910 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13911
13912 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013913 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013914 return status;
13915 }
13916
13917 /*set key mgmt type */
13918 if (req->crypto.n_akm_suites) {
13919 status =
13920 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13921 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013922 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013923 return status;
13924 }
13925 }
13926
13927 /*set pairwise cipher type */
13928 if (req->crypto.n_ciphers_pairwise) {
13929 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13930 req->crypto.
13931 ciphers_pairwise[0],
13932 true);
13933 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013934 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013935 return status;
13936 }
13937 } else {
13938 /*Reset previous cipher suite to none */
13939 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13940 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013941 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013942 return status;
13943 }
13944 }
13945
13946 /*set group cipher type */
13947 status =
13948 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13949 false);
13950
13951 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013952 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 return status;
13954 }
13955#ifdef WLAN_FEATURE_11W
13956 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13957#endif
13958
13959 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13960 if (req->ie_len) {
13961 status =
13962 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13963 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013964 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013965 return status;
13966 }
13967 }
13968
13969 /*incase of WEP set default key information */
13970 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013971 u8 key_len = req->key_len;
13972 u8 key_idx = req->key_idx;
13973
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013974 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13975 || (WLAN_CIPHER_SUITE_WEP104 ==
13976 req->crypto.ciphers_pairwise[0])
13977 ) {
13978 if (IW_AUTH_KEY_MGMT_802_1X
13979 ==
13980 (pWextState->
13981 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013982 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013983 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013984 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013985
Jeff Johnson68755312017-02-10 11:46:55 -080013986 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13987 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013988 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080013989 key_idx, key_len);
13990 qdf_mem_copy(&pWextState->roamProfile.
13991 Keys.
13992 KeyMaterial[key_idx][0],
13993 req->key, key_len);
13994 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013995 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013996 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013997 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013998 }
13999 }
14000 }
14001
14002 return status;
14003}
14004
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014005int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014006{
14007 unsigned long rc;
14008 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014009 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014010 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014011
14012 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014013 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14014 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014015 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014016 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14017 }
14018 /*
14019 * If firmware has already started roaming process, driver
14020 * needs to defer the processing of this disconnect request.
14021 *
14022 */
14023 if (hdd_is_roaming_in_progress(pAdapter)) {
14024 /*
14025 * Defer the disconnect action until firmware roaming
14026 * result is received. If STA is in connected state after
14027 * that, send the disconnect command to CSR, otherwise
14028 * CSR would have already sent disconnect event to upper
14029 * layer.
14030 */
14031
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014032 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014033 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14034 pAdapter->cfg80211_disconnect_reason =
14035 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14036 return 0;
14037 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014038
Jeff Johnson9edf9572016-10-03 15:24:49 -070014039 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014040 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14041 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14042 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014043 hdd_conn_set_connection_state(pAdapter,
14044 eConnectionState_Disconnecting);
14045 /* Issue disconnect to CSR */
14046 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014047
14048 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14049 pAdapter->sessionId,
14050 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14051 /*
14052 * Wait here instead of returning directly, this will block the
14053 * next connect command and allow processing of the scan for
14054 * ssid and the previous connect command in CSR. Else we might
14055 * hit some race conditions leading to SME and HDD out of sync.
14056 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014057 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014058 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014059 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014060 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014061 (int)status);
14062 pHddStaCtx->staDebugState = status;
14063 result = -EINVAL;
14064 goto disconnected;
14065 }
14066
14067 rc = wait_for_completion_timeout(
14068 &pAdapter->disconnect_comp_var,
14069 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014070 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014071 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014072 pAdapter->sessionId, pHddStaCtx->staDebugState);
14073 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014074 }
14075 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014076 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014078 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014079 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014080 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014081 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014082 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014083 }
14084 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014085disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014086 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14087 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014088}
14089
14090/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014091 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14092 * @adapter: Pointer to the HDD adapter
14093 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014094 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014095 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014096 * This function will start reassociation if prev_bssid is set and bssid/
14097 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014098 *
Naveen Rawat07332902016-07-27 09:13:17 -070014099 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014100 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014101#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14102 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014103static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14104 struct cfg80211_connect_params *req,
14105 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014106{
Naveen Rawat07332902016-07-27 09:13:17 -070014107 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014108 const uint8_t *bssid = NULL;
14109 uint16_t channel = 0;
14110
14111 if (req->bssid)
14112 bssid = req->bssid;
14113 else if (req->bssid_hint)
14114 bssid = req->bssid_hint;
14115
14116 if (req->channel)
14117 channel = req->channel->hw_value;
14118 else if (req->channel_hint)
14119 channel = req->channel_hint->hw_value;
14120
14121 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014122 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014123 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014124 channel, MAC_ADDR_ARRAY(bssid));
14125 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014126 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014127 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014128 }
Naveen Rawat07332902016-07-27 09:13:17 -070014129 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014130}
14131#else
Naveen Rawat07332902016-07-27 09:13:17 -070014132static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14133 struct cfg80211_connect_params *req,
14134 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014135{
Naveen Rawat07332902016-07-27 09:13:17 -070014136 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014137}
14138#endif
14139
14140/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014141 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14142 * @wiphy: Pointer to wiphy
14143 * @dev: Pointer to network device
14144 * @req: Pointer to cfg80211 connect request
14145 *
14146 * This function is used to start the association process
14147 *
14148 * Return: 0 for success, non-zero for failure
14149 */
14150static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14151 struct net_device *ndev,
14152 struct cfg80211_connect_params *req)
14153{
14154 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014155 u16 channel;
14156#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14157 const u8 *bssid_hint = req->bssid_hint;
14158#else
14159 const u8 *bssid_hint = NULL;
14160#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14162 hdd_context_t *pHddCtx;
14163
14164 ENTER();
14165
Anurag Chouhan6d760662016-02-20 16:05:43 +053014166 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014167 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014168 return -EINVAL;
14169 }
14170
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014171 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14172 hdd_err("invalid session id: %d", pAdapter->sessionId);
14173 return -EINVAL;
14174 }
14175
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014176 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014177 TRACE_CODE_HDD_CFG80211_CONNECT,
14178 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014179 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014180 hdd_device_mode_to_string(pAdapter->device_mode),
14181 pAdapter->device_mode);
14182
Krunal Sonib4326f22016-03-10 13:05:51 -080014183 if (pAdapter->device_mode != QDF_STA_MODE &&
14184 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014185 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014186 hdd_device_mode_to_string(pAdapter->device_mode),
14187 pAdapter->device_mode);
14188 return -EINVAL;
14189 }
14190
14191 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14192 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014193 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014194 return -EINVAL;
14195 }
14196
14197 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014198 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014199 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014200
Naveen Rawat07332902016-07-27 09:13:17 -070014201 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014202 return status;
14203
Agrawal Ashishf156e942016-08-04 14:54:47 +053014204 /* Try disconnecting if already in connected state */
14205 status = wlan_hdd_try_disconnect(pAdapter);
14206 if (0 > status) {
14207 hdd_err("Failed to disconnect the existing connection");
14208 return -EALREADY;
14209 }
14210
14211 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014212 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014213 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14214 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014215 pAdapter->device_mode),
14216 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014217 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014218 return -ECONNREFUSED;
14219 }
14220 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014221 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14222 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014223 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014224 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014225 return -ECONNREFUSED;
14226 }
14227 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014228
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014229 /*initialise security parameters */
14230 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14231
14232 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014233 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014234 return status;
14235 }
14236
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014237 if (req->channel)
14238 channel = req->channel->hw_value;
14239 else
14240 channel = 0;
14241 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14242 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014243 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014245 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014246 return status;
14247 }
14248 EXIT();
14249 return status;
14250}
14251
14252/**
14253 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14254 * @wiphy: Pointer to wiphy
14255 * @dev: Pointer to network device
14256 * @req: Pointer to cfg80211 connect request
14257 *
14258 * Return: 0 for success, non-zero for failure
14259 */
14260static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14261 struct net_device *ndev,
14262 struct cfg80211_connect_params *req)
14263{
14264 int ret;
14265 cds_ssr_protect(__func__);
14266 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14267 cds_ssr_unprotect(__func__);
14268
14269 return ret;
14270}
14271
14272/**
14273 * wlan_hdd_disconnect() - hdd disconnect api
14274 * @pAdapter: Pointer to adapter
14275 * @reason: Disconnect reason code
14276 *
14277 * This function is used to issue a disconnect request to SME
14278 *
14279 * Return: 0 for success, non-zero for failure
14280 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014281static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014282{
14283 int status, result = 0;
14284 unsigned long rc;
14285 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14286 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014287 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014288 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014289
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014290 ENTER();
14291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014292 status = wlan_hdd_validate_context(pHddCtx);
14293
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014294 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014295 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014296 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014297 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014298 status = sme_stop_roaming(hal, pAdapter->sessionId,
14299 eCsrHddIssued);
14300 }
14301 /*
14302 * If firmware has already started roaming process, driver
14303 * needs to defer the processing of this disconnect request.
14304 */
14305 if (hdd_is_roaming_in_progress(pAdapter)) {
14306 /*
14307 * Defer the disconnect action until firmware roaming
14308 * result is received. If STA is in connected state after
14309 * that, send the disconnect command to CSR, otherwise
14310 * CSR would have already sent disconnect event to upper
14311 * layer.
14312 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014313 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014314 pAdapter->defer_disconnect =
14315 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14316 pAdapter->cfg80211_disconnect_reason = reason;
14317 return 0;
14318 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014319
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014320 prev_conn_state = pHddStaCtx->conn_info.connState;
14321
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014322 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014323 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014324 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014325 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014326 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014327 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14328 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14329
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014330 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014331
14332 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14333 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014334 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14335 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014336 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014337 result = 0;
14338 goto disconnected;
14339 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14340 /*
14341 * Wait here instead of returning directly, this will block the
14342 * next connect command and allow processing of the scan for
14343 * ssid and the previous connect command in CSR. Else we might
14344 * hit some race conditions leading to SME and HDD out of sync.
14345 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014346 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014348 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014349 pHddStaCtx->staDebugState = status;
14350 result = -EINVAL;
14351 goto disconnected;
14352 }
14353 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14354 msecs_to_jiffies
14355 (WLAN_WAIT_TIME_DISCONNECT));
14356
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014357 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014358 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014359 result = -ETIMEDOUT;
14360 }
14361disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014362 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14363#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14364 /* Sending disconnect event to userspace for kernel version < 3.11
14365 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14366 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014367 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014368 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14369 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014370#endif
14371
14372 return result;
14373}
14374
14375/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014376 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14377 * @reason: ieee80211 reason code.
14378 *
14379 * This utility function helps log string conversion of reason code.
14380 *
14381 * Return: string conversion of reason code, if match found;
14382 * "Unknown" otherwise.
14383 */
14384static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14385{
14386 switch (reason) {
14387 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14388 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14389 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14390 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14391 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14392 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14393 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14394 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14395 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14396 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14397 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14398 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14399 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14400 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14401 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14402 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14403 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14404 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14405 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14406 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14407 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14408 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14409 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14410 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14411 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14412 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14413 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14414 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14415 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14416 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14417 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14418 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14419 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14420 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14421 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14422 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14423 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14424 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14425 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14426 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14427 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14428 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14429 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14430 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14431 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14432 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14433 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14434 default:
14435 return "Unknown";
14436 }
14437}
14438
14439/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014440 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14441 * @wiphy: Pointer to wiphy
14442 * @dev: Pointer to network device
14443 * @reason: Disconnect reason code
14444 *
14445 * This function is used to issue a disconnect request to SME
14446 *
14447 * Return: 0 for success, non-zero for failure
14448 */
14449static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14450 struct net_device *dev, u16 reason)
14451{
14452 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14453 int status;
14454 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14455 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14456#ifdef FEATURE_WLAN_TDLS
14457 uint8_t staIdx;
14458#endif
14459
14460 ENTER();
14461
Anurag Chouhan6d760662016-02-20 16:05:43 +053014462 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014463 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014464 return -EINVAL;
14465 }
14466
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014467 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014468 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014469 return -EINVAL;
14470 }
14471
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014472 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014473 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14474 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014475 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014476 hdd_device_mode_to_string(pAdapter->device_mode),
14477 pAdapter->device_mode, reason);
14478
14479 status = wlan_hdd_validate_context(pHddCtx);
14480
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014481 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014482 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014483
14484 /* Issue disconnect request to SME, if station is in connected state */
14485 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14486 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14487 eCsrRoamDisconnectReason reasonCode =
14488 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14489 hdd_scaninfo_t *pScanInfo;
14490
14491 switch (reason) {
14492 case WLAN_REASON_MIC_FAILURE:
14493 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14494 break;
14495
14496 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14497 case WLAN_REASON_DISASSOC_AP_BUSY:
14498 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14499 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14500 break;
14501
14502 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14503 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14504 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14505 break;
14506
14507 case WLAN_REASON_DEAUTH_LEAVING:
14508 reasonCode =
14509 pHddCtx->config->
14510 gEnableDeauthToDisassocMap ?
14511 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14512 eCSR_DISCONNECT_REASON_DEAUTH;
14513 break;
14514 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14515 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14516 break;
14517 default:
14518 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14519 break;
14520 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014521 pScanInfo = &pAdapter->scan_info;
14522 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014523 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014524 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014525 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014526 eCSR_SCAN_ABORT_DEFAULT);
14527 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014528 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014529#ifdef FEATURE_WLAN_TDLS
14530 /* First clean up the tdls peers if any */
14531 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14532 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14533 pAdapter->sessionId)
14534 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14535 uint8_t *mac;
14536 mac =
14537 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014538 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014539 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014540 pHddCtx->tdlsConnInfo[staIdx].staId,
14541 pAdapter->sessionId,
14542 MAC_ADDR_ARRAY(mac));
14543 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14544 (pAdapter),
14545 pAdapter->sessionId, mac);
14546 }
14547 }
14548#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014549 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14550 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014551 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14552 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014553 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554 return -EINVAL;
14555 }
14556 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014557 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014558 pHddStaCtx->conn_info.connState);
14559 }
14560
14561 return status;
14562}
14563
14564/**
14565 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14566 * @wiphy: Pointer to wiphy
14567 * @dev: Pointer to network device
14568 * @reason: Disconnect reason code
14569 *
14570 * Return: 0 for success, non-zero for failure
14571 */
14572static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14573 struct net_device *dev, u16 reason)
14574{
14575 int ret;
14576 cds_ssr_protect(__func__);
14577 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14578 cds_ssr_unprotect(__func__);
14579
14580 return ret;
14581}
14582
14583/**
14584 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14585 * @pAdapter: Pointer to adapter
14586 * @param: Pointer to IBSS parameters
14587 *
14588 * This function is used to initialize the security settings in IBSS mode
14589 *
14590 * Return: 0 for success, non-zero for failure
14591 */
14592static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14593 struct cfg80211_ibss_params
14594 *params)
14595{
14596 int status = 0;
14597 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14598 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14599 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14600
14601 ENTER();
14602
14603 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014604 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014605 pHddStaCtx->ibss_enc_key_installed = 0;
14606
14607 if (params->ie_len && (NULL != params->ie)) {
14608 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14609 params->ie_len, WLAN_EID_RSN)) {
14610 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14611 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14612 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14613 tDot11fIEWPA dot11WPAIE;
14614 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14615 u8 *ie;
14616
14617 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14618 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14619 params->ie_len,
14620 DOT11F_EID_WPA);
14621 if (NULL != ie) {
14622 pWextState->wpaVersion =
14623 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014624 /* Unpack the WPA IE
14625 * Skip past the EID byte and length byte
14626 * and four byte WiFi OUI
14627 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014628 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014629 &ie[2 + 4], ie[1] - 4,
14630 &dot11WPAIE, false);
14631 /*
14632 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014633 * encType for unicast cipher for
14634 * wpa-none is none
14635 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014636 encryptionType =
14637 hdd_translate_wpa_to_csr_encryption_type
14638 (dot11WPAIE.multicast_cipher);
14639 }
14640 }
14641
14642 status =
14643 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14644 params->ie_len);
14645
14646 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014647 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014648 return status;
14649 }
14650 }
14651
14652 pWextState->roamProfile.AuthType.authType[0] =
14653 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14654
14655 if (params->privacy) {
14656 /* Security enabled IBSS, At this time there is no information
14657 * available about the security paramters, so initialise the
14658 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14659 * The correct security parameters will be updated later in
14660 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14661 * set inorder enable privacy bit in beacons
14662 */
14663
14664 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14665 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014666 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014667 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14668 pWextState->roamProfile.EncryptionType.numEntries = 1;
14669 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14670 encryptionType;
14671 return status;
14672}
14673
14674/**
14675 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14676 * @wiphy: Pointer to wiphy
14677 * @dev: Pointer to network device
14678 * @param: Pointer to IBSS join parameters
14679 *
14680 * This function is used to create/join an IBSS network
14681 *
14682 * Return: 0 for success, non-zero for failure
14683 */
14684static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14685 struct net_device *dev,
14686 struct cfg80211_ibss_params *params)
14687{
14688 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14689 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14690 tCsrRoamProfile *pRoamProfile;
14691 int status;
14692 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14693 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014694 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014695 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014696
14697 ENTER();
14698
Anurag Chouhan6d760662016-02-20 16:05:43 +053014699 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014700 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014701 return -EINVAL;
14702 }
14703
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014704 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014705 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014706 return -EINVAL;
14707 }
14708
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014709 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014710 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14711 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014712 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014713 hdd_device_mode_to_string(pAdapter->device_mode),
14714 pAdapter->device_mode);
14715
14716 status = wlan_hdd_validate_context(pHddCtx);
14717
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014718 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014719 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014720
14721 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014722 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014723 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14724 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14725 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14726 int indx;
14727
14728 /* Get channel number */
14729 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014730 params->
14731 chandef.
14732 chan->
14733 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014734
14735 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14736 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014737 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014738 return -EOPNOTSUPP;
14739 }
14740
14741 for (indx = 0; indx < numChans; indx++) {
14742 if (channelNum == validChan[indx]) {
14743 break;
14744 }
14745 }
14746 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014747 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014748 return -EINVAL;
14749 }
14750 }
14751
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014752 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14753 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014754 hdd_err("This concurrency combination is not allowed");
14755 return -ECONNREFUSED;
14756 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014757
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014758 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014759 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014760 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014761
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014762 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14763 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014764 SIR_UPDATE_REASON_JOIN_IBSS);
14765 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014766 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014767 return -EINVAL;
14768 }
14769
14770 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014771 status = policy_mgr_wait_for_connection_update(
14772 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014773 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014774 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014775 return -EINVAL;
14776 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014777 }
14778
14779 /*Try disconnecting if already in connected state */
14780 status = wlan_hdd_try_disconnect(pAdapter);
14781 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014782 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014783 return -EALREADY;
14784 }
14785
14786 pRoamProfile = &pWextState->roamProfile;
14787
14788 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014789 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014790 return -EINVAL;
14791 }
14792
14793 /* enable selected protection checks in IBSS mode */
14794 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14795
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014796 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014797 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14798 pHddCtx->config->
14799 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014800 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014801 }
14802
14803 /* BSSID is provided by upper layers hence no need to AUTO generate */
14804 if (NULL != params->bssid) {
14805 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014806 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014807 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014808 return -EIO;
14809 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014810 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014811 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14812 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014813 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014814 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014815 return -EIO;
14816 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014817 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014818 }
14819 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14820 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14821 pRoamProfile->beaconInterval = params->beacon_interval;
14822 else {
14823 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014824 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014825 params->beacon_interval, pRoamProfile->beaconInterval);
14826 }
14827
14828 /* Set Channel */
14829 if (channelNum) {
14830 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014831 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014832 pRoamProfile->ChannelInfo.numOfChannels = 1;
14833 pHddStaCtx->conn_info.operationChannel = channelNum;
14834 pRoamProfile->ChannelInfo.ChannelList =
14835 &pHddStaCtx->conn_info.operationChannel;
14836 }
14837
14838 /* Initialize security parameters */
14839 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14840 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014841 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014842 return status;
14843 }
14844
14845 /* Issue connect start */
14846 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14847 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014848 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014849 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014850 operationChannel,
14851 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014852
14853 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014854 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014855 return status;
14856 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014857 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014858 return 0;
14859}
14860
14861/**
14862 * wlan_hdd_cfg80211_join_ibss() - join ibss
14863 * @wiphy: Pointer to wiphy
14864 * @dev: Pointer to network device
14865 * @param: Pointer to IBSS join parameters
14866 *
14867 * This function is used to create/join an IBSS network
14868 *
14869 * Return: 0 for success, non-zero for failure
14870 */
14871static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14872 struct net_device *dev,
14873 struct cfg80211_ibss_params *params)
14874{
14875 int ret = 0;
14876
14877 cds_ssr_protect(__func__);
14878 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14879 cds_ssr_unprotect(__func__);
14880
14881 return ret;
14882}
14883
14884/**
14885 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14886 * @wiphy: Pointer to wiphy
14887 * @dev: Pointer to network device
14888 *
14889 * This function is used to leave an IBSS network
14890 *
14891 * Return: 0 for success, non-zero for failure
14892 */
14893static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14894 struct net_device *dev)
14895{
14896 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14897 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14898 tCsrRoamProfile *pRoamProfile;
14899 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14900 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014901 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014902 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014903 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014904
14905 ENTER();
14906
Anurag Chouhan6d760662016-02-20 16:05:43 +053014907 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014908 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014909 return -EINVAL;
14910 }
14911
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014912 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014913 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014914 return -EINVAL;
14915 }
14916
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014917 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014918 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14919 pAdapter->sessionId,
14920 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14921 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014922 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014923 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014924
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014925 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014926 hdd_device_mode_to_string(pAdapter->device_mode),
14927 pAdapter->device_mode);
14928 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014929 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014930 return -EIO;
14931 }
14932
14933 pRoamProfile = &pWextState->roamProfile;
14934
14935 /* Issue disconnect only if interface type is set to IBSS */
14936 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014937 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014938 return -EINVAL;
14939 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014940 /* Clearing add IE of beacon */
14941 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14942 sizeof(tSirMacAddr));
14943 updateIE.smeSessionId = pAdapter->sessionId;
14944 updateIE.ieBufferlength = 0;
14945 updateIE.pAdditionIEBuffer = NULL;
14946 updateIE.append = true;
14947 updateIE.notify = true;
14948 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14949 &updateIE,
14950 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014951 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014952 }
14953
14954 /* Reset WNI_CFG_PROBE_RSP Flags */
14955 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014956
14957 /* Issue Disconnect request */
14958 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14959 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14960 pAdapter->sessionId,
14961 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014962 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014963 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014964 hal_status);
14965 return -EAGAIN;
14966 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014967
14968 /* wait for mc thread to cleanup and then return to upper stack
14969 * so by the time upper layer calls the change interface, we are
14970 * all set to proceed further
14971 */
14972 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14973 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14974 if (!rc) {
14975 hdd_err("Failed to disconnect, timed out");
14976 return -ETIMEDOUT;
14977 }
14978
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014979 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014980 return 0;
14981}
14982
14983/**
14984 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14985 * @wiphy: Pointer to wiphy
14986 * @dev: Pointer to network device
14987 *
14988 * This function is used to leave an IBSS network
14989 *
14990 * Return: 0 for success, non-zero for failure
14991 */
14992static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14993 struct net_device *dev)
14994{
14995 int ret = 0;
14996
14997 cds_ssr_protect(__func__);
14998 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14999 cds_ssr_unprotect(__func__);
15000
15001 return ret;
15002}
15003
15004/**
15005 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15006 * @wiphy: Pointer to wiphy
15007 * @changed: Parameters changed
15008 *
15009 * This function is used to set the phy parameters. RTS Threshold/FRAG
15010 * Threshold/Retry Count etc.
15011 *
15012 * Return: 0 for success, non-zero for failure
15013 */
15014static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15015 u32 changed)
15016{
15017 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15018 tHalHandle hHal = pHddCtx->hHal;
15019 int status;
15020
15021 ENTER();
15022
Anurag Chouhan6d760662016-02-20 16:05:43 +053015023 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015024 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015025 return -EINVAL;
15026 }
15027
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015028 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015029 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15030 NO_SESSION, wiphy->rts_threshold));
15031 status = wlan_hdd_validate_context(pHddCtx);
15032
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015033 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015034 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015035
15036 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15037 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15038 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15039
15040 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15041 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015042 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 rts_threshold);
15044 return -EINVAL;
15045 }
15046
15047 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15048 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015049 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015050 rts_threshold);
15051 return -EIO;
15052 }
15053
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015054 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015055 }
15056
15057 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15058 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15059 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15060 wiphy->frag_threshold;
15061
15062 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15063 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015064 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015065 frag_threshold);
15066 return -EINVAL;
15067 }
15068
15069 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15070 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015071 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015072 frag_threshold);
15073 return -EIO;
15074 }
15075
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015076 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015077 }
15078
15079 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15080 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15081 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15082 wiphy->retry_short : wiphy->retry_long;
15083
15084 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15085 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015086 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087 return -EINVAL;
15088 }
15089
15090 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15091 if (0 != sme_cfg_set_int(hHal,
15092 WNI_CFG_LONG_RETRY_LIMIT,
15093 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015094 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015095 retry_value);
15096 return -EIO;
15097 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015098 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015099 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15100 if (0 != sme_cfg_set_int(hHal,
15101 WNI_CFG_SHORT_RETRY_LIMIT,
15102 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015103 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015104 retry_value);
15105 return -EIO;
15106 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015107 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015108 }
15109 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015110 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015111 return 0;
15112}
15113
15114/**
15115 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15116 * @wiphy: Pointer to wiphy
15117 * @changed: Parameters changed
15118 *
15119 * Return: 0 for success, non-zero for failure
15120 */
15121static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15122{
15123 int ret;
15124
15125 cds_ssr_protect(__func__);
15126 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15127 cds_ssr_unprotect(__func__);
15128
15129 return ret;
15130}
15131
15132/**
15133 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15134 * key
15135 * @wiphy: Pointer to wiphy
15136 * @dev: Pointer to network device
15137 * @key_index: Key index
15138 *
15139 * Return: 0
15140 */
15141static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15142 struct net_device *netdev,
15143 u8 key_index)
15144{
15145 ENTER();
15146 return 0;
15147}
15148
15149/**
15150 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15151 * wlan_hdd_set_default_mgmt_key
15152 * @wiphy: pointer to wiphy
15153 * @netdev: pointer to net_device structure
15154 * @key_index: key index
15155 *
15156 * Return: 0 on success, error number on failure
15157 */
15158static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15159 struct net_device *netdev,
15160 u8 key_index)
15161{
15162 int ret;
15163
15164 cds_ssr_protect(__func__);
15165 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15166 cds_ssr_unprotect(__func__);
15167
15168 return ret;
15169}
15170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015171/**
15172 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15173 * @wiphy: Pointer to wiphy
15174 * @dev: Pointer to network device
15175 * @params: Pointer to tx queue parameters
15176 *
15177 * Return: 0
15178 */
15179static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15180 struct net_device *dev,
15181 struct ieee80211_txq_params *params)
15182{
15183 ENTER();
15184 return 0;
15185}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015186
15187/**
15188 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15189 * @wiphy: pointer to wiphy
15190 * @netdev: pointer to net_device structure
15191 * @params: pointer to ieee80211_txq_params
15192 *
15193 * Return: 0 on success, error number on failure
15194 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015195static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15196 struct net_device *dev,
15197 struct ieee80211_txq_params *params)
15198{
15199 int ret;
15200
15201 cds_ssr_protect(__func__);
15202 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15203 cds_ssr_unprotect(__func__);
15204
15205 return ret;
15206}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015207
15208/**
15209 * __wlan_hdd_cfg80211_del_station() - delete station v2
15210 * @wiphy: Pointer to wiphy
15211 * @param: Pointer to delete station parameter
15212 *
15213 * Return: 0 for success, non-zero for failure
15214 */
15215static
15216int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15217 struct net_device *dev,
15218 struct tagCsrDelStaParams *pDelStaParams)
15219{
15220 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15221 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015222 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015223 hdd_hostapd_state_t *hapd_state;
15224 int status;
15225 uint8_t staId;
15226 uint8_t *mac;
15227
15228 ENTER();
15229
Anurag Chouhan6d760662016-02-20 16:05:43 +053015230 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015231 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015232 return -EINVAL;
15233 }
15234
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015235 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015236 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015237 return -EINVAL;
15238 }
15239
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015240 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015241 TRACE_CODE_HDD_CFG80211_DEL_STA,
15242 pAdapter->sessionId, pAdapter->device_mode));
15243
15244 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15245 status = wlan_hdd_validate_context(pHddCtx);
15246
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015247 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015248 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015249
15250 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15251
Krunal Sonib4326f22016-03-10 13:05:51 -080015252 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15253 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015254
15255 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15256 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015257 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015258 return 0;
15259 }
15260
Anurag Chouhanc5548422016-02-24 18:33:27 +053015261 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015262 uint16_t i;
15263 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15264 if ((pAdapter->aStaInfo[i].isUsed) &&
15265 (!pAdapter->aStaInfo[i].
15266 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015267 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015268 mac,
15269 pAdapter->aStaInfo[i].
15270 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015271 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015272 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15273 hdd_ipa_wlan_evt(pAdapter,
15274 pAdapter->
15275 aStaInfo[i].
15276 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015277 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015278 mac);
15279 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015280 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015281 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015282 MAC_ADDR_ARRAY(mac));
15283
15284 if (pHddCtx->dev_dfs_cac_status ==
15285 DFS_CAC_IN_PROGRESS)
15286 goto fn_end;
15287
Wei Song2f76f642016-11-18 16:32:53 +080015288 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015289 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015290 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015291 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015292 hdd_softap_sta_deauth(pAdapter,
15293 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015294 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295 pAdapter->aStaInfo[i].
15296 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015297 qdf_status =
15298 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015299 &hapd_state->
15300 qdf_sta_disassoc_event,
15301 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015302 if (!QDF_IS_STATUS_SUCCESS(
15303 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015304 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015305 }
15306 }
15307 }
15308 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015309 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015310 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015311 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015312 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015313 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015314 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015315 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015316 MAC_ADDR_ARRAY(mac));
15317 return -ENOENT;
15318 }
15319
15320 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15321 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015322 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015323 }
15324
15325 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15326 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015327 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015328 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015329 MAC_ADDR_ARRAY(mac));
15330 return -ENOENT;
15331 }
15332
15333 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15334
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015335 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015336 MAC_ADDR_ARRAY(mac));
15337
15338 /* Case: SAP in ACS selected DFS ch and client connected
15339 * Now Radar detected. Then if random channel is another
15340 * DFS ch then new CAC is initiated and no TX allowed.
15341 * So do not send any mgmt frames as it will timeout
15342 * during CAC.
15343 */
15344
15345 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15346 goto fn_end;
15347
Wei Song2f76f642016-11-18 16:32:53 +080015348 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015349 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15350 (pAdapter), pAdapter->sessionId,
15351 (uint8_t *)&pDelStaParams->peerMacAddr,
15352 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015353 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015354 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015355 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015356 pAdapter->aStaInfo[staId].isDeauthInProgress =
15357 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015358 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015359 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015360 MAC_ADDR_ARRAY(mac));
15361 return -ENOENT;
15362 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015363 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015364 &hapd_state->
15365 qdf_sta_disassoc_event,
15366 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015367 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015368 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015369 }
15370 }
15371 }
15372
15373fn_end:
15374 EXIT();
15375 return 0;
15376}
15377
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015378#if defined(USE_CFG80211_DEL_STA_V2)
15379/**
15380 * wlan_hdd_del_station() - delete station wrapper
15381 * @adapter: pointer to the hdd adapter
15382 *
15383 * Return: None
15384 */
15385void wlan_hdd_del_station(hdd_adapter_t *adapter)
15386{
15387 struct station_del_parameters del_sta;
15388 del_sta.mac = NULL;
15389 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15390 del_sta.reason_code = eCsrForcedDeauthSta;
15391
15392 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15393 &del_sta);
15394}
15395#else
15396void wlan_hdd_del_station(hdd_adapter_t *adapter)
15397{
15398 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15399}
15400#endif
15401
15402#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015403/**
15404 * wlan_hdd_cfg80211_del_station() - delete station v2
15405 * @wiphy: Pointer to wiphy
15406 * @param: Pointer to delete station parameter
15407 *
15408 * Return: 0 for success, non-zero for failure
15409 */
15410int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15411 struct net_device *dev,
15412 struct station_del_parameters *param)
15413#else
15414/**
15415 * wlan_hdd_cfg80211_del_station() - delete station
15416 * @wiphy: Pointer to wiphy
15417 * @mac: Pointer to station mac address
15418 *
15419 * Return: 0 for success, non-zero for failure
15420 */
15421#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15422int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15423 struct net_device *dev,
15424 const uint8_t *mac)
15425#else
15426int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15427 struct net_device *dev,
15428 uint8_t *mac)
15429#endif
15430#endif
15431{
15432 int ret;
15433 struct tagCsrDelStaParams delStaParams;
15434
15435 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015436#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015437 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015438 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015439 return -EINVAL;
15440 }
15441 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15442 param->subtype, &delStaParams);
15443#else
15444 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15445 (SIR_MAC_MGMT_DEAUTH >> 4),
15446 &delStaParams);
15447#endif
15448 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15449 cds_ssr_unprotect(__func__);
15450
15451 return ret;
15452}
15453
15454/**
15455 * __wlan_hdd_cfg80211_add_station() - add station
15456 * @wiphy: Pointer to wiphy
15457 * @mac: Pointer to station mac address
15458 * @pmksa: Pointer to add station parameter
15459 *
15460 * Return: 0 for success, non-zero for failure
15461 */
15462static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15463 struct net_device *dev,
15464 const uint8_t *mac,
15465 struct station_parameters *params)
15466{
15467 int status = -EPERM;
15468#ifdef FEATURE_WLAN_TDLS
15469 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15470 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15471 u32 mask, set;
15472
15473 ENTER();
15474
Anurag Chouhan6d760662016-02-20 16:05:43 +053015475 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015476 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015477 return -EINVAL;
15478 }
15479
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015480 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015481 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015482 return -EINVAL;
15483 }
15484
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015485 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015486 TRACE_CODE_HDD_CFG80211_ADD_STA,
15487 pAdapter->sessionId, params->listen_interval));
15488
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015489 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015490 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491
15492 mask = params->sta_flags_mask;
15493
15494 set = params->sta_flags_set;
15495
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015496 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015497 MAC_ADDR_ARRAY(mac));
15498
15499 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15500 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015501#if defined(CONVERGED_TDLS_ENABLE)
15502 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15503 dev, mac);
15504#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015505 status =
15506 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015507#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015508 }
15509 }
15510#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015511 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015512 return status;
15513}
15514
15515/**
15516 * wlan_hdd_cfg80211_add_station() - add station
15517 * @wiphy: Pointer to wiphy
15518 * @mac: Pointer to station mac address
15519 * @pmksa: Pointer to add station parameter
15520 *
15521 * Return: 0 for success, non-zero for failure
15522 */
15523#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15524static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15525 struct net_device *dev,
15526 const uint8_t *mac,
15527 struct station_parameters *params)
15528#else
15529static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15530 struct net_device *dev, uint8_t *mac,
15531 struct station_parameters *params)
15532#endif
15533{
15534 int ret;
15535
15536 cds_ssr_protect(__func__);
15537 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15538 cds_ssr_unprotect(__func__);
15539
15540 return ret;
15541}
15542
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015543/**
15544 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15545 * @wiphy: Pointer to wiphy
15546 * @dev: Pointer to network device
15547 * @pmksa: Pointer to set pmksa parameter
15548 *
15549 * Return: 0 for success, non-zero for failure
15550 */
15551static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15552 struct net_device *dev,
15553 struct cfg80211_pmksa *pmksa)
15554{
15555 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15556 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15557 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015558 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015559 int status;
15560 tPmkidCacheInfo pmk_id;
15561
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015562 ENTER();
15563
Anurag Chouhan6d760662016-02-20 16:05:43 +053015564 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015565 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015566 return -EINVAL;
15567 }
15568
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015569 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015570 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015571 return -EINVAL;
15572 }
15573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015574 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015575 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015576 return -EINVAL;
15577 }
15578
15579 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015580 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015581 pmksa->bssid, pmksa->pmkid);
15582 return -EINVAL;
15583 }
15584
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015585 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015586 MAC_ADDR_ARRAY(pmksa->bssid));
15587
15588 status = wlan_hdd_validate_context(pHddCtx);
15589
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015590 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015591 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015592
15593 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15594
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015595 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15596 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015597
15598 /* Add to the PMKSA ID Cache in CSR */
15599 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15600 &pmk_id, 1, false);
15601
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015602 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015603 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15604 pAdapter->sessionId, result));
15605
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015606 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015607 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015608}
15609
15610/**
15611 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15612 * @wiphy: Pointer to wiphy
15613 * @dev: Pointer to network device
15614 * @pmksa: Pointer to set pmksa parameter
15615 *
15616 * Return: 0 for success, non-zero for failure
15617 */
15618static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15619 struct net_device *dev,
15620 struct cfg80211_pmksa *pmksa)
15621{
15622 int ret;
15623
15624 cds_ssr_protect(__func__);
15625 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15626 cds_ssr_unprotect(__func__);
15627
15628 return ret;
15629}
15630
15631/**
15632 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15633 * @wiphy: Pointer to wiphy
15634 * @dev: Pointer to network device
15635 * @pmksa: Pointer to pmksa parameter
15636 *
15637 * Return: 0 for success, non-zero for failure
15638 */
15639static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15640 struct net_device *dev,
15641 struct cfg80211_pmksa *pmksa)
15642{
15643 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15644 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15645 tHalHandle halHandle;
15646 int status = 0;
15647
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015648 ENTER();
15649
Anurag Chouhan6d760662016-02-20 16:05:43 +053015650 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015651 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015652 return -EINVAL;
15653 }
15654
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015655 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15656 hdd_err("invalid session id: %d", pAdapter->sessionId);
15657 return -EINVAL;
15658 }
15659
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015660 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015661 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015662 return -EINVAL;
15663 }
15664
15665 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015666 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015667 return -EINVAL;
15668 }
15669
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015670 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015671 MAC_ADDR_ARRAY(pmksa->bssid));
15672
15673 status = wlan_hdd_validate_context(pHddCtx);
15674
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015675 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015676 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015677
15678 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15679
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015680 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015681 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15682 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015683 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015684 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015685 sme_roam_del_pmkid_from_cache(halHandle,
15686 pAdapter->sessionId, pmksa->bssid,
15687 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015688 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015689 MAC_ADDR_ARRAY(pmksa->bssid));
15690 status = -EINVAL;
15691 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015692 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015693 return status;
15694}
15695
15696/**
15697 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15698 * @wiphy: Pointer to wiphy
15699 * @dev: Pointer to network device
15700 * @pmksa: Pointer to pmksa parameter
15701 *
15702 * Return: 0 for success, non-zero for failure
15703 */
15704static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15705 struct net_device *dev,
15706 struct cfg80211_pmksa *pmksa)
15707{
15708 int ret;
15709
15710 cds_ssr_protect(__func__);
15711 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15712 cds_ssr_unprotect(__func__);
15713
15714 return ret;
15715
15716}
15717
15718/**
15719 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15720 * @wiphy: Pointer to wiphy
15721 * @dev: Pointer to network device
15722 *
15723 * Return: 0 for success, non-zero for failure
15724 */
15725static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15726 struct net_device *dev)
15727{
15728 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15729 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15730 tHalHandle halHandle;
15731 int status = 0;
15732
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015733 ENTER();
15734
Anurag Chouhan6d760662016-02-20 16:05:43 +053015735 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015736 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015737 return -EINVAL;
15738 }
15739
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015740 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15741 hdd_err("invalid session id: %d", pAdapter->sessionId);
15742 return -EINVAL;
15743 }
15744
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015745 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015746
15747 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15748 status = wlan_hdd_validate_context(pHddCtx);
15749
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015750 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015751 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015752
15753 /* Retrieve halHandle */
15754 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15755
15756 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015757 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015758 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15759 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015760 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015761 status = -EINVAL;
15762 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015763 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015764 return status;
15765}
15766
15767/**
15768 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15769 * @wiphy: Pointer to wiphy
15770 * @dev: Pointer to network device
15771 *
15772 * Return: 0 for success, non-zero for failure
15773 */
15774static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15775 struct net_device *dev)
15776{
15777 int ret;
15778
15779 cds_ssr_protect(__func__);
15780 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15781 cds_ssr_unprotect(__func__);
15782
15783 return ret;
15784}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015785
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015786#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015787/**
15788 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15789 * @wiphy: Pointer to wiphy
15790 * @dev: Pointer to network device
15791 * @ftie: Pointer to fast transition ie parameter
15792 *
15793 * Return: 0 for success, non-zero for failure
15794 */
15795static int
15796__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15797 struct net_device *dev,
15798 struct cfg80211_update_ft_ies_params *ftie)
15799{
15800 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15801 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15802 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15803 int status;
15804
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015805 ENTER();
15806
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015807 status = wlan_hdd_validate_context(hdd_ctx);
15808 if (status)
15809 return status;
15810
Anurag Chouhan6d760662016-02-20 16:05:43 +053015811 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015812 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015813 return -EINVAL;
15814 }
15815
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015816 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15817 hdd_err("invalid session id: %d", pAdapter->sessionId);
15818 return -EINVAL;
15819 }
15820
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015821 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015822 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15823 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15824 /* Added for debug on reception of Re-assoc Req. */
15825 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015826 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015828 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015829 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015830 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015831 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015832
15833 /* Pass the received FT IEs to SME */
15834 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15835 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015836 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015837 return 0;
15838}
15839
15840/**
15841 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15842 * @wiphy: Pointer to wiphy
15843 * @dev: Pointer to network device
15844 * @ftie: Pointer to fast transition ie parameter
15845 *
15846 * Return: 0 for success, non-zero for failure
15847 */
15848static int
15849wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15850 struct net_device *dev,
15851 struct cfg80211_update_ft_ies_params *ftie)
15852{
15853 int ret;
15854
15855 cds_ssr_protect(__func__);
15856 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15857 cds_ssr_unprotect(__func__);
15858
15859 return ret;
15860}
15861#endif
15862
Mukul Sharma3d36c392017-01-18 18:39:12 +053015863void wlan_hdd_cfg80211_update_replay_counter_callback(
15864 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15865
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015866{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015867 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15868 uint8_t temp_replay_counter[8];
15869 int i;
15870 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015871
15872 ENTER();
15873
Mukul Sharma3d36c392017-01-18 18:39:12 +053015874 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015875 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015876 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015877 }
15878
Mukul Sharma3d36c392017-01-18 18:39:12 +053015879 if (!gtk_rsp_param) {
15880 hdd_err("gtk_rsp_param is Null");
15881 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015882 }
15883
Mukul Sharma3d36c392017-01-18 18:39:12 +053015884 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015885 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015886 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015887 }
15888
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015889 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015890 gtk_rsp_param->replay_counter);
15891 /* convert little to big endian since supplicant works on big endian */
15892 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15893 for (i = 0; i < 8; i++)
15894 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015895
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015896 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015897 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015898 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015899 gtk_rsp_param->bssid.bytes,
15900 temp_replay_counter, GFP_KERNEL);
15901out:
15902 EXIT();
15903
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015904}
15905
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015906static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015907int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015908 struct net_device *dev,
15909 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015910{
15911 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015912 int result, i;
15913 struct pmo_gtk_req *gtk_req = NULL;
15914 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15915 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015916 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015917
15918 ENTER();
15919
Anurag Chouhan6d760662016-02-20 16:05:43 +053015920 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015921 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015922 result = -EINVAL;
15923 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015924 }
15925
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015926 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15927 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015928 result = -EINVAL;
15929 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015930 }
15931
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015932 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015933 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15934 pAdapter->sessionId, pAdapter->device_mode));
15935
Mukul Sharma3d36c392017-01-18 18:39:12 +053015936 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015937 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015938 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015939
Mukul Sharma3d36c392017-01-18 18:39:12 +053015940 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15941 if (!gtk_req) {
15942 hdd_err("cannot allocate gtk_req");
15943 result = -ENOMEM;
15944 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015945 }
15946
Mukul Sharma3d36c392017-01-18 18:39:12 +053015947 /* convert big to little endian since driver work on little endian */
15948 buf = (uint8_t *)&gtk_req->replay_counter;
15949 for (i = 0; i < 8; i++)
15950 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015951
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015952 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015953 gtk_req->replay_counter);
15954 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15955 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15956 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15957 if (status != QDF_STATUS_SUCCESS) {
15958 hdd_err("Failed to cache GTK Offload");
15959 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015960 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015961out:
15962 if (gtk_req)
15963 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015964 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015965
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015966 return result;
15967}
15968
15969/**
15970 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15971 * @wiphy: Pointer to wiphy
15972 * @dev: Pointer to network device
15973 * @data: Pointer to rekey data
15974 *
15975 * This function is used to offload GTK rekeying job to the firmware.
15976 *
15977 * Return: 0 for success, non-zero for failure
15978 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015979static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015980int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15981 struct net_device *dev,
15982 struct cfg80211_gtk_rekey_data *data)
15983{
15984 int ret;
15985
15986 cds_ssr_protect(__func__);
15987 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15988 cds_ssr_unprotect(__func__);
15989
15990 return ret;
15991}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015992
15993/**
15994 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15995 * @wiphy: Pointer to wiphy
15996 * @dev: Pointer to network device
15997 * @param: Pointer to access control parameter
15998 *
15999 * Return: 0 for success, non-zero for failure
16000 */
16001static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16002 struct net_device *dev,
16003 const struct cfg80211_acl_data *params)
16004{
16005 int i;
16006 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16007 hdd_hostapd_state_t *pHostapdState;
16008 tsap_Config_t *pConfig;
16009 v_CONTEXT_t p_cds_context = NULL;
16010 hdd_context_t *pHddCtx;
16011 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016012 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016013
16014 ENTER();
16015
Anurag Chouhan6d760662016-02-20 16:05:43 +053016016 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016017 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016018 return -EINVAL;
16019 }
16020
16021 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016022 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016023 return -EINVAL;
16024 }
16025
16026 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16027 status = wlan_hdd_validate_context(pHddCtx);
16028
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016029 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016030 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016031
16032 p_cds_context = pHddCtx->pcds_context;
16033 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16034
16035 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016036 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016037 return -EINVAL;
16038 }
16039
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016040 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016041 params->n_acl_entries);
16042
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016043 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016044 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16045 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016046 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016047 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16048
16049 /* default value */
16050 pConfig->num_accept_mac = 0;
16051 pConfig->num_deny_mac = 0;
16052
16053 /**
16054 * access control policy
16055 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16056 * listed in hostapd.deny file.
16057 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16058 * listed in hostapd.accept file.
16059 */
16060 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16061 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16062 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16063 params->acl_policy) {
16064 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16065 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016066 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016067 params->acl_policy);
16068 return -ENOTSUPP;
16069 }
16070
16071 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16072 pConfig->num_accept_mac = params->n_acl_entries;
16073 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016074 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016075 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016076 MAC_ADDR_ARRAY(
16077 params->mac_addrs[i].addr));
16078
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016079 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016080 params->mac_addrs[i].addr,
16081 sizeof(qcmacaddr));
16082 }
16083 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16084 pConfig->num_deny_mac = params->n_acl_entries;
16085 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016086 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016087 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016088 MAC_ADDR_ARRAY(
16089 params->mac_addrs[i].addr));
16090
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016091 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016092 params->mac_addrs[i].addr,
16093 sizeof(qcmacaddr));
16094 }
16095 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016096 qdf_status = wlansap_set_mac_acl(
16097 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016098 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016099 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016100 return -EINVAL;
16101 }
16102 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016103 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016104 hdd_device_mode_to_string(pAdapter->device_mode),
16105 pAdapter->device_mode);
16106 return -EINVAL;
16107 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016108 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016109 return 0;
16110}
16111
16112/**
16113 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16114 * __wlan_hdd_cfg80211_set_mac_acl
16115 * @wiphy: pointer to wiphy structure
16116 * @dev: pointer to net_device
16117 * @params: pointer to cfg80211_acl_data
16118 *
16119 * Return; 0 on success, error number otherwise
16120 */
16121static int
16122wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16123 struct net_device *dev,
16124 const struct cfg80211_acl_data *params)
16125{
16126 int ret;
16127
16128 cds_ssr_protect(__func__);
16129 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16130 cds_ssr_unprotect(__func__);
16131
16132 return ret;
16133}
16134
16135#ifdef WLAN_NL80211_TESTMODE
16136#ifdef FEATURE_WLAN_LPHB
16137/**
16138 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16139 * @pHddCtx: Pointer to hdd context
16140 * @lphbInd: Pointer to low power heart beat indication parameter
16141 *
16142 * Return: none
16143 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016144static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016145 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016146{
16147 struct sk_buff *skb;
16148
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016149 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016150
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016151 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016152 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016153
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016154 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016155 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016156 return;
16157 }
16158
16159 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016160 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016161 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016162 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016163 return;
16164 }
16165
16166 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016167 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016168 goto nla_put_failure;
16169 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016170 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016171 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016172 goto nla_put_failure;
16173 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016174 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16175 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016176 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016177 goto nla_put_failure;
16178 }
16179 cfg80211_testmode_event(skb, GFP_ATOMIC);
16180 return;
16181
16182nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016183 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016184 kfree_skb(skb);
16185
16186 return;
16187}
16188#endif /* FEATURE_WLAN_LPHB */
16189
16190/**
16191 * __wlan_hdd_cfg80211_testmode() - test mode
16192 * @wiphy: Pointer to wiphy
16193 * @data: Data pointer
16194 * @len: Data length
16195 *
16196 * Return: 0 for success, non-zero for failure
16197 */
16198static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16199 void *data, int len)
16200{
16201 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16202 int err;
16203 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16204
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016205 ENTER();
16206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016207 err = wlan_hdd_validate_context(pHddCtx);
16208 if (err)
16209 return err;
16210
16211 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16212 len, wlan_hdd_tm_policy);
16213 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016214 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016215 return err;
16216 }
16217
16218 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016219 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016220 return -EINVAL;
16221 }
16222
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016223 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016224 TRACE_CODE_HDD_CFG80211_TESTMODE,
16225 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016226 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16227#ifdef FEATURE_WLAN_LPHB
16228 /* Low Power Heartbeat configuration request */
16229 case WLAN_HDD_TM_CMD_WLAN_HB:
16230 {
16231 int buf_len;
16232 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016233 struct pmo_lphb_req *hb_params = NULL;
16234 struct pmo_lphb_req *hb_params_temp = NULL;
16235 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016236
16237 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016238 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016239 return -EINVAL;
16240 }
16241
16242 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16243 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16244
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016245 hb_params_temp = (struct pmo_lphb_req *) buf;
16246 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16247 && (hb_params_temp->params.lphb_tcp_params.
16248 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016249 return -EINVAL;
16250
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016251 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16252 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016253 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016254 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016255 return -ENOMEM;
16256 }
16257
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016258 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016259 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16260 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016261 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016262 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016263 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016264
16265 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016266 return 0;
16267 }
16268#endif /* FEATURE_WLAN_LPHB */
16269
16270#if defined(QCA_WIFI_FTM)
16271 case WLAN_HDD_TM_CMD_WLAN_FTM:
16272 {
16273 int buf_len;
16274 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016275 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016276 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016277 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016278 return -EINVAL;
16279 }
16280
16281 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16282 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16283
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016284 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016285
16286 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16287
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016288 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016289 err = -EBUSY;
16290 break;
16291 }
16292#endif
16293
16294 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016295 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016296 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16297 return -EOPNOTSUPP;
16298 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016299 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016300 return err;
16301}
16302
16303/**
16304 * wlan_hdd_cfg80211_testmode() - test mode
16305 * @wiphy: Pointer to wiphy
16306 * @dev: Pointer to network device
16307 * @data: Data pointer
16308 * @len: Data length
16309 *
16310 * Return: 0 for success, non-zero for failure
16311 */
16312static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16313#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16314 struct wireless_dev *wdev,
16315#endif
16316 void *data, int len)
16317{
16318 int ret;
16319
16320 cds_ssr_protect(__func__);
16321 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16322 cds_ssr_unprotect(__func__);
16323
16324 return ret;
16325}
16326
16327#if defined(QCA_WIFI_FTM)
16328/**
16329 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16330 * @buf: Pointer to buffer
16331 * @buf_len: Buffer length
16332 *
16333 * Return: none
16334 */
16335void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16336{
16337 struct sk_buff *skb;
16338 hdd_context_t *hdd_ctx;
16339
16340 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016341 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016342 return;
16343 }
16344
Anurag Chouhan6d760662016-02-20 16:05:43 +053016345 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016346 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016347 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016348 return;
16349 }
16350
16351 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16352 buf_len, GFP_KERNEL);
16353 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016354 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016355 return;
16356 }
16357
16358 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16359 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16360 goto nla_put_failure;
16361
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016362 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016363
16364 cfg80211_testmode_event(skb, GFP_KERNEL);
16365 return;
16366
16367nla_put_failure:
16368 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016369 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016370}
16371#endif
16372#endif /* CONFIG_NL80211_TESTMODE */
16373
16374#ifdef QCA_HT_2040_COEX
16375/**
16376 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16377 * @wiphy: Pointer to wiphy
16378 * @dev: Pointer to network device
16379 * @chandef: Pointer to channel definition parameter
16380 *
16381 * Return: 0 for success, non-zero for failure
16382 */
16383static int
16384__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16385 struct net_device *dev,
16386 struct cfg80211_chan_def *chandef)
16387{
16388 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16389 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016390 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016391 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016392 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016393
Anurag Chouhan6d760662016-02-20 16:05:43 +053016394 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016395 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016396 return -EINVAL;
16397 }
16398
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016399 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16400 hdd_err("invalid session id: %d", pAdapter->sessionId);
16401 return -EINVAL;
16402 }
16403
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016404 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16405 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016406 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016407 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016408
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016409 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016410 sme_get_config_param(pHddCtx->hHal, &sme_config);
16411 switch (chandef->width) {
16412 case NL80211_CHAN_WIDTH_20:
16413 if (sme_config.csrConfig.channelBondingMode24GHz !=
16414 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16415 sme_config.csrConfig.channelBondingMode24GHz =
16416 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16417 sme_update_config(pHddCtx->hHal, &sme_config);
16418 cbModeChange = true;
16419 }
16420 break;
16421
16422 case NL80211_CHAN_WIDTH_40:
16423 if (sme_config.csrConfig.channelBondingMode24GHz ==
16424 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16425 if (NL80211_CHAN_HT40MINUS ==
16426 cfg80211_get_chandef_type(chandef))
16427 sme_config.csrConfig.channelBondingMode24GHz =
16428 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16429 else
16430 sme_config.csrConfig.channelBondingMode24GHz =
16431 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16432 sme_update_config(pHddCtx->hHal, &sme_config);
16433 cbModeChange = true;
16434 }
16435 break;
16436
16437 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016438 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016439 return -EINVAL;
16440 }
16441
16442 if (!cbModeChange)
16443 return 0;
16444
Krunal Sonib4326f22016-03-10 13:05:51 -080016445 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016446 return 0;
16447
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016448 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016449 sme_config.csrConfig.channelBondingMode24GHz);
16450
16451 /* Change SAP ht2040 mode */
16452 status = hdd_set_sap_ht2040_mode(pAdapter,
16453 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016454 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016455 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016456 return -EINVAL;
16457 }
16458
16459 return 0;
16460}
16461
16462/**
16463 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16464 * @wiphy: Pointer to wiphy
16465 * @dev: Pointer to network device
16466 * @chandef: Pointer to channel definition parameter
16467 *
16468 * Return: 0 for success, non-zero for failure
16469 */
16470static int
16471wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16472 struct net_device *dev,
16473 struct cfg80211_chan_def *chandef)
16474{
16475 int ret;
16476
16477 cds_ssr_protect(__func__);
16478 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16479 cds_ssr_unprotect(__func__);
16480
16481 return ret;
16482}
16483#endif
16484
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016485#ifdef CHANNEL_SWITCH_SUPPORTED
16486/**
16487 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16488 * channel in SAP/GO
16489 * @wiphy: wiphy pointer
16490 * @dev: dev pointer.
16491 * @csa_params: Change channel params
16492 *
16493 * This function is called to switch channel in SAP/GO
16494 *
16495 * Return: 0 if success else return non zero
16496 */
16497static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16498 struct net_device *dev,
16499 struct cfg80211_csa_settings *csa_params)
16500{
16501 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16502 hdd_context_t *hdd_ctx;
16503 uint8_t channel;
16504 uint16_t freq;
16505 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016506 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016507
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016508 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016509 csa_params->chandef.chan->center_freq);
16510
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016511 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16512 hdd_err("invalid session id: %d", adapter->sessionId);
16513 return -EINVAL;
16514 }
16515
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016516 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16517 ret = wlan_hdd_validate_context(hdd_ctx);
16518
16519 if (0 != ret)
16520 return ret;
16521
Krunal Sonib4326f22016-03-10 13:05:51 -080016522 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16523 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016524 return -ENOTSUPP;
16525
16526 freq = csa_params->chandef.chan->center_freq;
16527 channel = cds_freq_to_chan(freq);
16528
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016529 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16530
16531 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016532 return ret;
16533}
16534
16535/**
16536 * wlan_hdd_cfg80211_channel_switch()- function to switch
16537 * channel in SAP/GO
16538 * @wiphy: wiphy pointer
16539 * @dev: dev pointer.
16540 * @csa_params: Change channel params
16541 *
16542 * This function is called to switch channel in SAP/GO
16543 *
16544 * Return: 0 if success else return non zero
16545 */
16546static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16547 struct net_device *dev,
16548 struct cfg80211_csa_settings *csa_params)
16549{
16550 int ret;
16551
16552 cds_ssr_protect(__func__);
16553 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16554 cds_ssr_unprotect(__func__);
16555 return ret;
16556}
16557#endif
16558
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016559/**
16560 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16561 * translation from NL to policy manager type
16562 * @type: Generic connection mode type defined in NL
16563 *
16564 *
16565 * This function provides the type translation
16566 *
16567 * Return: cds_con_mode enum
16568 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016569enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016570 enum nl80211_iftype type)
16571{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016572 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016573 switch (type) {
16574 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016575 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016576 break;
16577 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016578 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016579 break;
16580 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016581 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016582 break;
16583 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016584 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016585 break;
16586 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016587 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016588 break;
16589 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016590 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016591 }
16592 return mode;
16593}
16594
16595/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016596 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16597 * @wiphy: Handle to struct wiphy to get handle to module context.
16598 * @chandef: Contains information about the capture channel to be set.
16599 *
16600 * This interface is called if and only if monitor mode interface alone is
16601 * active.
16602 *
16603 * Return: 0 success or error code on failure.
16604 */
16605static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16606 struct cfg80211_chan_def *chandef)
16607{
16608 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16609 hdd_adapter_t *adapter;
16610 hdd_station_ctx_t *sta_ctx;
16611 struct hdd_mon_set_ch_info *ch_info;
16612 QDF_STATUS status;
16613 tHalHandle hal_hdl;
16614 struct qdf_mac_addr bssid;
16615 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016616 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016617 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016618 int ret;
16619 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16620
16621 ENTER();
16622
16623 ret = wlan_hdd_validate_context(hdd_ctx);
16624 if (ret)
16625 return ret;
16626
16627 hal_hdl = hdd_ctx->hHal;
16628
16629 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16630 if (!adapter)
16631 return -EIO;
16632
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016633 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016634 adapter->dev->name, chan_num, chandef->chan->center_freq);
16635
16636 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16637 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016638 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16639 roam_profile.ChannelInfo.numOfChannels = 1;
16640 roam_profile.phyMode = ch_info->phy_mode;
16641 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016642 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016643
16644 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16645 QDF_MAC_ADDR_SIZE);
16646
16647 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016648 /*
16649 * CDS api expects secondary channel for calculating
16650 * the channel params
16651 */
16652 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16653 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16654 if (chan_num >= 1 && chan_num <= 5)
16655 sec_ch = chan_num + 4;
16656 else if (chan_num >= 6 && chan_num <= 13)
16657 sec_ch = chan_num - 4;
16658 }
16659 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016660 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16661 &roam_profile);
16662 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016663 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016664 status);
16665 ret = qdf_status_to_os_return(status);
16666 return ret;
16667 }
16668 EXIT();
16669 return 0;
16670}
16671
16672/**
16673 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16674 * @wiphy: Handle to struct wiphy to get handle to module context.
16675 * @chandef: Contains information about the capture channel to be set.
16676 *
16677 * This interface is called if and only if monitor mode interface alone is
16678 * active.
16679 *
16680 * Return: 0 success or error code on failure.
16681 */
16682static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16683 struct cfg80211_chan_def *chandef)
16684{
16685 int ret;
16686
16687 cds_ssr_protect(__func__);
16688 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16689 cds_ssr_unprotect(__func__);
16690 return ret;
16691}
16692
16693/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016694 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16695 * @adapter: pointer to adapter
16696 *
16697 * Wrapper function to clear link layer stats.
16698 * return - void
16699 */
16700void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16701{
16702 tSirLLStatsClearReq link_layer_stats_clear_req;
16703 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16704
Mukul Sharma491021c2016-09-29 21:39:19 +053016705 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16706 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016707 link_layer_stats_clear_req.stopReq = 0;
16708 link_layer_stats_clear_req.reqId = 1;
16709 link_layer_stats_clear_req.staId = adapter->sessionId;
16710 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16711
16712 return;
16713}
16714
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016715/**
16716 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16717 * @adapter: HDD Adapter
16718 *
16719 * If roaming is in progress and there is a request to
16720 * disconnect the session, then it is deferred. Once
16721 * roaming is complete/aborted, then this routine is
16722 * used to resume the disconnect that was deferred
16723 *
16724 * Return: None
16725 */
16726void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16727{
16728 switch (adapter->defer_disconnect) {
16729 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16730 adapter->defer_disconnect = 0;
16731 wlan_hdd_disconnect(adapter,
16732 adapter->cfg80211_disconnect_reason);
16733 break;
16734 case DEFER_DISCONNECT_TRY_DISCONNECT:
16735 wlan_hdd_try_disconnect(adapter);
16736 adapter->defer_disconnect = 0;
16737 break;
16738 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016739 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016740 adapter->defer_disconnect);
16741 break;
16742 }
16743}
16744
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016745#define CNT_DIFF(cur, prev) \
16746 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16747#define MAX_COUNT 0xffffffff
16748static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16749 struct scan_chan_info *chan,
16750 struct scan_chan_info *info, uint32_t cmd_flag)
16751{
16752 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16753 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16754 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16755
16756 mutex_lock(&hdd_ctx->chan_info_lock);
16757
16758 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16759 qdf_mem_zero(chan, sizeof(*chan));
16760
16761 chan->freq = info->freq;
16762 chan->noise_floor = info->noise_floor;
16763 chan->clock_freq = info->clock_freq;
16764 chan->cmd_flag = info->cmd_flag;
16765 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16766
16767 chan->rx_clear_count =
16768 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16769
16770 chan->tx_frame_count =
16771 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16772
16773 mutex_unlock(&hdd_ctx->chan_info_lock);
16774
16775}
16776#undef CNT_DIFF
16777#undef MAX_COUNT
16778
16779/**
16780 * wlan_hdd_chan_info_cb() - channel info callback
16781 * @chan_info: struct scan_chan_info
16782 *
16783 * Store channel info into HDD context
16784 *
16785 * Return: None.
16786 */
16787static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16788{
16789 hdd_context_t *hdd_ctx;
16790 struct scan_chan_info *chan;
16791 uint8_t idx;
16792
16793 ENTER();
16794
16795 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16796 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16797 hdd_err("hdd_ctx is invalid");
16798 return;
16799 }
16800
16801 if (!hdd_ctx->chan_info) {
16802 hdd_err("chan_info is NULL");
16803 return;
16804 }
16805
16806 chan = hdd_ctx->chan_info;
16807 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16808 if (chan[idx].freq == info->freq) {
16809 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16810 info->cmd_flag);
16811 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16812 chan[idx].cmd_flag, chan[idx].freq,
16813 chan[idx].noise_floor,
16814 chan[idx].cycle_count, chan[idx].rx_clear_count,
16815 chan[idx].clock_freq, chan[idx].cmd_flag,
16816 chan[idx].tx_frame_count, idx);
16817 if (chan[idx].freq == 0)
16818 break;
16819
16820 }
16821 }
16822
16823 EXIT();
16824}
16825
16826/**
16827 * wlan_hdd_init_chan_info() - init chan info in hdd context
16828 * @hdd_ctx: HDD context pointer
16829 *
16830 * Return: none
16831 */
16832void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16833{
16834 uint8_t num_2g, num_5g, index = 0;
16835
16836 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16837 hdd_info("SNR monitoring is disabled");
16838 return;
16839 }
16840
16841 hdd_ctx->chan_info =
16842 qdf_mem_malloc(sizeof(struct scan_chan_info)
16843 * QDF_MAX_NUM_CHAN);
16844 if (hdd_ctx->chan_info == NULL) {
16845 hdd_err("Failed to malloc for chan info");
16846 return;
16847 }
16848 mutex_init(&hdd_ctx->chan_info_lock);
16849
16850 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16851 for (; index < num_2g; index++) {
16852 hdd_ctx->chan_info[index].freq =
16853 hdd_channels_2_4_ghz[index].center_freq;
16854 }
16855
16856 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16857 for (; (index - num_2g) < num_5g; index++) {
16858 if (cds_is_dsrc_channel(
16859 hdd_channels_5_ghz[index - num_2g].center_freq))
16860 continue;
16861 hdd_ctx->chan_info[index].freq =
16862 hdd_channels_5_ghz[index - num_2g].center_freq;
16863 }
16864 sme_set_chan_info_callback(hdd_ctx->hHal,
16865 &wlan_hdd_chan_info_cb);
16866}
16867
16868/**
16869 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16870 * @hdd_ctx: hdd context pointer
16871 *
16872 * Return: none
16873 */
16874void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16875{
16876 struct scan_chan_info *chan;
16877
16878 chan = hdd_ctx->chan_info;
16879 hdd_ctx->chan_info = NULL;
16880 if (chan)
16881 qdf_mem_free(chan);
16882}
16883
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016884/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016885 * struct cfg80211_ops - cfg80211_ops
16886 *
16887 * @add_virtual_intf: Add virtual interface
16888 * @del_virtual_intf: Delete virtual interface
16889 * @change_virtual_intf: Change virtual interface
16890 * @change_station: Change station
16891 * @add_beacon: Add beacon in sap mode
16892 * @del_beacon: Delete beacon in sap mode
16893 * @set_beacon: Set beacon in sap mode
16894 * @start_ap: Start ap
16895 * @change_beacon: Change beacon
16896 * @stop_ap: Stop ap
16897 * @change_bss: Change bss
16898 * @add_key: Add key
16899 * @get_key: Get key
16900 * @del_key: Delete key
16901 * @set_default_key: Set default key
16902 * @set_channel: Set channel
16903 * @scan: Scan
16904 * @connect: Connect
16905 * @disconnect: Disconnect
16906 * @join_ibss = Join ibss
16907 * @leave_ibss = Leave ibss
16908 * @set_wiphy_params = Set wiphy params
16909 * @set_tx_power = Set tx power
16910 * @get_tx_power = get tx power
16911 * @remain_on_channel = Remain on channel
16912 * @cancel_remain_on_channel = Cancel remain on channel
16913 * @mgmt_tx = Tx management frame
16914 * @mgmt_tx_cancel_wait = Cancel management tx wait
16915 * @set_default_mgmt_key = Set default management key
16916 * @set_txq_params = Set tx queue parameters
16917 * @get_station = Get station
16918 * @set_power_mgmt = Set power management
16919 * @del_station = Delete station
16920 * @add_station = Add station
16921 * @set_pmksa = Set pmksa
16922 * @del_pmksa = Delete pmksa
16923 * @flush_pmksa = Flush pmksa
16924 * @update_ft_ies = Update FT IEs
16925 * @tdls_mgmt = Tdls management
16926 * @tdls_oper = Tdls operation
16927 * @set_rekey_data = Set rekey data
16928 * @sched_scan_start = Scheduled scan start
16929 * @sched_scan_stop = Scheduled scan stop
16930 * @resume = Resume wlan
16931 * @suspend = Suspend wlan
16932 * @set_mac_acl = Set mac acl
16933 * @testmode_cmd = Test mode command
16934 * @set_ap_chanwidth = Set AP channel bandwidth
16935 * @dump_survey = Dump survey
16936 * @key_mgmt_set_pmk = Set pmk key management
16937 */
16938static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16939 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16940 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16941 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16942 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016943 .start_ap = wlan_hdd_cfg80211_start_ap,
16944 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16945 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016946 .change_bss = wlan_hdd_cfg80211_change_bss,
16947 .add_key = wlan_hdd_cfg80211_add_key,
16948 .get_key = wlan_hdd_cfg80211_get_key,
16949 .del_key = wlan_hdd_cfg80211_del_key,
16950 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16951 .scan = wlan_hdd_cfg80211_scan,
16952 .connect = wlan_hdd_cfg80211_connect,
16953 .disconnect = wlan_hdd_cfg80211_disconnect,
16954 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16955 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16956 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16957 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16958 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16959 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16960 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16961 .mgmt_tx = wlan_hdd_mgmt_tx,
16962 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16963 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16964 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016965 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016966 .get_station = wlan_hdd_cfg80211_get_station,
16967 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16968 .del_station = wlan_hdd_cfg80211_del_station,
16969 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016970 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16971 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16972 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016973#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016974 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16975#endif
16976#ifdef FEATURE_WLAN_TDLS
16977 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16978 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16979#endif
16980#ifdef WLAN_FEATURE_GTK_OFFLOAD
16981 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16982#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16983#ifdef FEATURE_WLAN_SCAN_PNO
16984 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16985 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16986#endif /*FEATURE_WLAN_SCAN_PNO */
16987 .resume = wlan_hdd_cfg80211_resume_wlan,
16988 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16989 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16990#ifdef WLAN_NL80211_TESTMODE
16991 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16992#endif
16993#ifdef QCA_HT_2040_COEX
16994 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16995#endif
16996 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016997#ifdef CHANNEL_SWITCH_SUPPORTED
16998 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16999#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017000 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017001#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17002 defined(CFG80211_ABORT_SCAN)
17003 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17004#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017005};