blob: e93a9b51b6b12f3c3024532036694d9831e4484f [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 */
Wu Gao84d120c2017-03-24 18:46:00 +080010583#ifdef CONVERGED_P2P_ENABLE
10584void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10585{
10586 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10587 /* Register for all P2P action, public action etc frames */
10588 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10589
10590 ENTER();
10591
10592 /* Register frame indication call back */
10593 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10594
10595 /* Register for p2p ack indication */
10596 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10597
10598 /* Right now we are registering these frame when driver is getting
10599 * initialized. Once we will move to 2.6.37 kernel, in which we have
10600 * frame register ops, we will move this code as a part of that
10601 */
10602
10603 /* GAS Initial Request */
10604 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10605 (uint8_t *) GAS_INITIAL_REQ,
10606 GAS_INITIAL_REQ_SIZE);
10607
10608 /* GAS Initial Response */
10609 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10610 (uint8_t *) GAS_INITIAL_RSP,
10611 GAS_INITIAL_RSP_SIZE);
10612
10613 /* GAS Comeback Request */
10614 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10615 (uint8_t *) GAS_COMEBACK_REQ,
10616 GAS_COMEBACK_REQ_SIZE);
10617
10618 /* GAS Comeback Response */
10619 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10620 (uint8_t *) GAS_COMEBACK_RSP,
10621 GAS_COMEBACK_RSP_SIZE);
10622
10623 /* WNM BSS Transition Request frame */
10624 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10625 (uint8_t *) WNM_BSS_ACTION_FRAME,
10626 WNM_BSS_ACTION_FRAME_SIZE);
10627
10628 /* WNM-Notification */
10629 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10630 (uint8_t *) WNM_NOTIFICATION_FRAME,
10631 WNM_NOTIFICATION_FRAME_SIZE);
10632}
10633#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010634void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10635{
10636 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10637 /* Register for all P2P action, public action etc frames */
10638 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10639
10640 ENTER();
10641
Abhishek Singh7996eb72015-12-30 17:24:02 +053010642 /* Register frame indication call back */
10643 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10644
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010645 /* Register for p2p ack indication */
10646 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10647
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010648 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010649 * initialized. Once we will move to 2.6.37 kernel, in which we have
10650 * frame register ops, we will move this code as a part of that
10651 */
10652
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010653 /* GAS Initial Request */
10654 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10655 (uint8_t *) GAS_INITIAL_REQ,
10656 GAS_INITIAL_REQ_SIZE);
10657
10658 /* GAS Initial Response */
10659 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10660 (uint8_t *) GAS_INITIAL_RSP,
10661 GAS_INITIAL_RSP_SIZE);
10662
10663 /* GAS Comeback Request */
10664 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10665 (uint8_t *) GAS_COMEBACK_REQ,
10666 GAS_COMEBACK_REQ_SIZE);
10667
10668 /* GAS Comeback Response */
10669 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10670 (uint8_t *) GAS_COMEBACK_RSP,
10671 GAS_COMEBACK_RSP_SIZE);
10672
10673 /* P2P Public Action */
10674 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10675 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10676 P2P_PUBLIC_ACTION_FRAME_SIZE);
10677
10678 /* P2P Action */
10679 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10680 (uint8_t *) P2P_ACTION_FRAME,
10681 P2P_ACTION_FRAME_SIZE);
10682
10683 /* WNM BSS Transition Request frame */
10684 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10685 (uint8_t *) WNM_BSS_ACTION_FRAME,
10686 WNM_BSS_ACTION_FRAME_SIZE);
10687
10688 /* WNM-Notification */
10689 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10690 (uint8_t *) WNM_NOTIFICATION_FRAME,
10691 WNM_NOTIFICATION_FRAME_SIZE);
10692}
Wu Gao84d120c2017-03-24 18:46:00 +080010693#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010694
10695void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10696{
10697 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10698 /* Register for all P2P action, public action etc frames */
10699 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10700
10701 ENTER();
10702
10703 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010704 * initialized. Once we will move to 2.6.37 kernel, in which we have
10705 * frame register ops, we will move this code as a part of that
10706 */
10707
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010708 /* GAS Initial Request */
10709
10710 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10711 (uint8_t *) GAS_INITIAL_REQ,
10712 GAS_INITIAL_REQ_SIZE);
10713
10714 /* GAS Initial Response */
10715 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10716 (uint8_t *) GAS_INITIAL_RSP,
10717 GAS_INITIAL_RSP_SIZE);
10718
10719 /* GAS Comeback Request */
10720 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10721 (uint8_t *) GAS_COMEBACK_REQ,
10722 GAS_COMEBACK_REQ_SIZE);
10723
10724 /* GAS Comeback Response */
10725 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10726 (uint8_t *) GAS_COMEBACK_RSP,
10727 GAS_COMEBACK_RSP_SIZE);
10728
10729 /* P2P Public Action */
10730 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10731 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10732 P2P_PUBLIC_ACTION_FRAME_SIZE);
10733
10734 /* P2P Action */
10735 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10736 (uint8_t *) P2P_ACTION_FRAME,
10737 P2P_ACTION_FRAME_SIZE);
10738
10739 /* WNM-Notification */
10740 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10741 (uint8_t *) WNM_NOTIFICATION_FRAME,
10742 WNM_NOTIFICATION_FRAME_SIZE);
10743}
10744
10745#ifdef FEATURE_WLAN_WAPI
10746void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10747 const uint8_t *mac_addr, const uint8_t *key,
10748 int key_Len)
10749{
10750 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10751 tCsrRoamSetKey setKey;
10752 bool isConnected = true;
10753 int status = 0;
10754 uint32_t roamId = 0xFF;
10755 uint8_t *pKeyPtr = NULL;
10756 int n = 0;
10757
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010758 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010759 hdd_device_mode_to_string(pAdapter->device_mode),
10760 pAdapter->device_mode);
10761
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010762 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010763 setKey.keyId = key_index; /* Store Key ID */
10764 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10765 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10766 setKey.paeRole = 0; /* the PAE role */
10767 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010768 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010769 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010770 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010771 }
10772 setKey.keyLength = key_Len;
10773 pKeyPtr = setKey.Key;
10774 memcpy(pKeyPtr, key, key_Len);
10775
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010776 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010778 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010779 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010780
10781 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10782 if (isConnected) {
10783 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10784 pAdapter->sessionId, &setKey, &roamId);
10785 }
10786 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010787 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10789 }
10790}
10791#endif /* FEATURE_WLAN_WAPI */
10792
10793uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10794 uint8_t eid)
10795{
10796 int left = length;
10797 uint8_t *ptr = (uint8_t *)ies_ptr;
10798 uint8_t elem_id, elem_len;
10799
10800 while (left >= 2) {
10801 elem_id = ptr[0];
10802 elem_len = ptr[1];
10803 left -= 2;
10804 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010805 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 eid, elem_len, left);
10807 return NULL;
10808 }
10809 if (elem_id == eid) {
10810 return ptr;
10811 }
10812
10813 left -= elem_len;
10814 ptr += (elem_len + 2);
10815 }
10816 return NULL;
10817}
10818
10819/*
10820 * FUNCTION: wlan_hdd_validate_operation_channel
10821 * called by wlan_hdd_cfg80211_start_bss() and
10822 * wlan_hdd_set_channel()
10823 * This function validates whether given channel is part of valid
10824 * channel list.
10825 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010826QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010827 int channel)
10828{
10829
10830 uint32_t num_ch = 0;
10831 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10832 u32 indx = 0;
10833 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10834 uint8_t fValidChannel = false, count = 0;
10835 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10836
10837 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10838
10839 if (hdd_pConfig_ini->sapAllowAllChannel) {
10840 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010841 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010842 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010843 fValidChannel = true;
10844 break;
10845 }
10846 }
10847 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010848 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010849 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010850 }
10851 } else {
10852 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10853 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010854 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010855 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 }
10857 for (indx = 0; indx < num_ch; indx++) {
10858 if (channel == valid_ch[indx]) {
10859 break;
10860 }
10861 }
10862
10863 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010864 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010865 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010866 }
10867 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010868 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010869
10870}
10871
10872#ifdef DHCP_SERVER_OFFLOAD
10873static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10874{
10875 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10876 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10877 uint8_t numEntries = 0;
10878 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10879 uint8_t num;
10880 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010881 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010882 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010883 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010884 return;
10885 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010886 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10887 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10888 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10889 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10890 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10891 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010892 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893 goto end;
10894 }
10895 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010896 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010897 goto end;
10898 }
10899 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010900 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010901 goto end;
10902 }
10903 for (num = 0; num < numEntries; num++) {
10904 temp = srv_ip[num];
10905 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10906 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010907 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010908 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010909 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010910 goto end;
10911 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010912 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010913end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010914 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010915 return;
10916}
10917#endif /* DHCP_SERVER_OFFLOAD */
10918
10919static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10920 struct net_device *dev,
10921 struct bss_parameters *params)
10922{
10923 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10924 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10925 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010926 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010927
10928 ENTER();
10929
Anurag Chouhan6d760662016-02-20 16:05:43 +053010930 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010931 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010932 return -EINVAL;
10933 }
10934
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010935 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10936 hdd_err("invalid session id: %d", pAdapter->sessionId);
10937 return -EINVAL;
10938 }
10939
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010940 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10942 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010943 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010944 hdd_device_mode_to_string(pAdapter->device_mode),
10945 pAdapter->device_mode, params->ap_isolate);
10946
10947 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10948 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010949 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010950 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010951
Krunal Sonib4326f22016-03-10 13:05:51 -080010952 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10953 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010954 return -EOPNOTSUPP;
10955 }
10956
10957 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010958 * want to update this parameter
10959 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 if (-1 != params->ap_isolate) {
10961 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10962 !!params->ap_isolate;
10963
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010964 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010965 pAdapter->sessionId,
10966 pAdapter->sessionCtx.
10967 ap.
10968 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010969 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010970 ret = -EINVAL;
10971 }
10972 }
10973
10974 EXIT();
10975 return ret;
10976}
10977
Krunal Soni8c37e322016-02-03 16:08:37 -080010978/**
10979 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10980 * @ndev: pointer to net device provided by supplicant
10981 * @type: type of the interface, upper layer wanted to change
10982 *
10983 * Upper layer provides the new interface mode that needs to be changed
10984 * for given net device
10985 *
10986 * Return: success or failure in terms of integer value
10987 */
10988static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010989 enum nl80211_iftype type)
10990{
Krunal Soni8c37e322016-02-03 16:08:37 -080010991 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10992 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10993 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010994 hdd_wext_state_t *wext;
10995 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010996 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010997
10998 ENTER();
10999
Krunal Soni8c37e322016-02-03 16:08:37 -080011000 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011001 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002 return 0;
11003 }
11004
11005 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011006 hdd_stop_adapter(hdd_ctx, adapter, true);
11007 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011008 wdev->iftype = type;
11009 /*Check for sub-string p2p to confirm its a p2p interface */
11010 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011011 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011012 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011013 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011014 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011015 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011016 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011017 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011018 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011019 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011020 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011021 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11022 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011023 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11024 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011025 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011026 adapter->scan_info.scanAddIE.length;
11027 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011028 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011029 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11030 wext->roamProfile.phyMode =
11031 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11032 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011033 EXIT();
11034 return status;
11035}
11036
11037static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11038 struct net_device *dev,
11039 struct bss_parameters *params)
11040{
11041 int ret;
11042
11043 cds_ssr_protect(__func__);
11044 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11045 cds_ssr_unprotect(__func__);
11046
11047 return ret;
11048}
11049
11050/* FUNCTION: wlan_hdd_change_country_code_cd
11051 * to wait for contry code completion
11052 */
11053void *wlan_hdd_change_country_code_cb(void *pAdapter)
11054{
11055 hdd_adapter_t *call_back_pAdapter = pAdapter;
11056 complete(&call_back_pAdapter->change_country_code);
11057 return NULL;
11058}
11059
Rajeev Kumar98edb772016-01-19 12:42:19 -080011060/**
11061 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11062 * @wiphy: Pointer to the wiphy structure
11063 * @ndev: Pointer to the net device
11064 * @type: Interface type
11065 * @flags: Flags for change interface
11066 * @params: Pointer to change interface parameters
11067 *
11068 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011069 */
11070static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11071 struct net_device *ndev,
11072 enum nl80211_iftype type,
11073 u32 *flags,
11074 struct vif_params *params)
11075{
11076 struct wireless_dev *wdev;
11077 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11078 hdd_context_t *pHddCtx;
11079 tCsrRoamProfile *pRoamProfile = NULL;
11080 eCsrRoamBssType LastBSSType;
11081 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011082 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011083 int status;
11084
11085 ENTER();
11086
Anurag Chouhan6d760662016-02-20 16:05:43 +053011087 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011088 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011089 return -EINVAL;
11090 }
11091
11092 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11093 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011094 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011095 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011097 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11099 pAdapter->sessionId, type));
11100
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011101 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011102 pAdapter->device_mode, type);
11103
Arun Khandavallifae92942016-08-01 13:31:08 +053011104 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11105 if (status) {
11106 hdd_err("Failed to start modules");
11107 return -EINVAL;
11108 }
11109
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011110 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011111 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11112 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011113 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011114 return -EINVAL;
11115 }
11116
11117 pConfig = pHddCtx->config;
11118 wdev = ndev->ieee80211_ptr;
11119
11120 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011121 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11122 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011123
Nitesh Shahe6359752017-02-23 19:57:50 +053011124 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011125 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11126 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11127 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11128 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011129 hdd_wext_state_t *pWextState =
11130 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11131
11132 pRoamProfile = &pWextState->roamProfile;
11133 LastBSSType = pRoamProfile->BSSType;
11134
11135 switch (type) {
11136 case NL80211_IFTYPE_STATION:
11137 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011138 case NL80211_IFTYPE_ADHOC:
11139 if (type == NL80211_IFTYPE_ADHOC) {
11140 wlan_hdd_tdls_exit(pAdapter);
11141 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011142 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011143 }
11144 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11145 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011146 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011147 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011148 if (hdd_start_adapter(pAdapter)) {
11149 hdd_err("Failed to start adapter :%d",
11150 pAdapter->device_mode);
11151 return -EINVAL;
11152 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011153 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011154 case NL80211_IFTYPE_AP:
11155 case NL80211_IFTYPE_P2P_GO:
11156 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011157 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 (type ==
11159 NL80211_IFTYPE_AP) ? "SoftAP" :
11160 "P2pGo");
11161
11162 /* Cancel any remain on channel for GO mode */
11163 if (NL80211_IFTYPE_P2P_GO == type) {
11164 wlan_hdd_cancel_existing_remain_on_channel
11165 (pAdapter);
11166 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011167
Arun Khandavallifae92942016-08-01 13:31:08 +053011168 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011169 /* De-init the adapter */
11170 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11171 memset(&pAdapter->sessionCtx, 0,
11172 sizeof(pAdapter->sessionCtx));
11173 pAdapter->device_mode =
11174 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011175 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11176 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177
11178 /*
11179 * Fw will take care incase of concurrency
11180 */
11181
Krunal Sonib4326f22016-03-10 13:05:51 -080011182 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011183 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011184 /* To meet Android requirements create
11185 * a randomized MAC address of the
11186 * form 02:1A:11:Fx:xx:xx
11187 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011188 get_random_bytes(&ndev->dev_addr[3], 3);
11189 ndev->dev_addr[0] = 0x02;
11190 ndev->dev_addr[1] = 0x1A;
11191 ndev->dev_addr[2] = 0x11;
11192 ndev->dev_addr[3] |= 0xF0;
11193 memcpy(pAdapter->macAddressCurrent.
11194 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011195 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196 pr_info("wlan: Generated HotSpot BSSID "
11197 MAC_ADDRESS_STR "\n",
11198 MAC_ADDR_ARRAY(ndev->dev_addr));
11199 }
11200
11201 hdd_set_ap_ops(pAdapter->dev);
11202
Arun Khandavallifae92942016-08-01 13:31:08 +053011203 if (hdd_start_adapter(pAdapter)) {
11204 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205 return -EINVAL;
11206 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011207 /* Interface type changed update in wiphy structure */
11208 if (wdev) {
11209 wdev->iftype = type;
11210 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011211 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011212 return -EINVAL;
11213 }
11214 goto done;
11215 }
11216
11217 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011218 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011219 return -EOPNOTSUPP;
11220 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011221 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11222 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011223 switch (type) {
11224 case NL80211_IFTYPE_STATION:
11225 case NL80211_IFTYPE_P2P_CLIENT:
11226 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011227 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11228 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011229 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011230 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011231 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011232 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011233 pAdapter->device_mode);
11234 return -EINVAL;
11235 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011236 goto done;
11237
11238 case NL80211_IFTYPE_AP:
11239 case NL80211_IFTYPE_P2P_GO:
11240 wdev->iftype = type;
11241 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011242 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011243 goto done;
11244
11245 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011246 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011247 return -EOPNOTSUPP;
11248 }
11249 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011250 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011251 pAdapter->device_mode);
11252 return -EOPNOTSUPP;
11253 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011254done:
11255 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011256 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11257 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011259 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260
11261 EXIT();
11262 return 0;
11263}
11264
Rajeev Kumar98edb772016-01-19 12:42:19 -080011265/**
11266 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11267 * @wiphy: Pointer to the wiphy structure
11268 * @ndev: Pointer to the net device
11269 * @type: Interface type
11270 * @flags: Flags for change interface
11271 * @params: Pointer to change interface parameters
11272 *
11273 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011274 */
11275static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11276 struct net_device *ndev,
11277 enum nl80211_iftype type,
11278 u32 *flags,
11279 struct vif_params *params)
11280{
11281 int ret;
11282
11283 cds_ssr_protect(__func__);
11284 ret =
11285 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11286 cds_ssr_unprotect(__func__);
11287
11288 return ret;
11289}
11290
Frank Liud4b2fa02017-03-29 11:46:48 +080011291#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011292static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11293 int index, uint8_t match)
11294{
11295 int i;
11296 for (i = 0; i < index; i++) {
11297 if (arr[i] == match)
11298 return true;
11299 }
11300 return false;
11301}
11302#endif
11303
11304/**
11305 * __wlan_hdd_change_station() - change station
11306 * @wiphy: Pointer to the wiphy structure
11307 * @dev: Pointer to the net device.
11308 * @mac: bssid
11309 * @params: Pointer to station parameters
11310 *
11311 * Return: 0 for success, error number on failure.
11312 */
11313#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11314static int __wlan_hdd_change_station(struct wiphy *wiphy,
11315 struct net_device *dev,
11316 const uint8_t *mac,
11317 struct station_parameters *params)
11318#else
11319static int __wlan_hdd_change_station(struct wiphy *wiphy,
11320 struct net_device *dev,
11321 uint8_t *mac,
11322 struct station_parameters *params)
11323#endif
11324{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011325 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011326 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11327 hdd_context_t *pHddCtx;
11328 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011329 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011330#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011331 tCsrStaParams StaParams = { 0 };
11332 uint8_t isBufSta = 0;
11333 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011334 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011335#endif
11336 int ret;
11337
11338 ENTER();
11339
Anurag Chouhan6d760662016-02-20 16:05:43 +053011340 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011341 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011342 return -EINVAL;
11343 }
11344
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011345 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011346 TRACE_CODE_HDD_CHANGE_STATION,
11347 pAdapter->sessionId, params->listen_interval));
11348
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011349 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11350 hdd_err("invalid session id: %d", pAdapter->sessionId);
11351 return -EINVAL;
11352 }
11353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11355 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011356 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011357 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011358
11359 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11360
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011361 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011362
Krunal Sonib4326f22016-03-10 13:05:51 -080011363 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11364 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011365 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11366 status =
11367 hdd_softap_change_sta_state(pAdapter,
11368 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011369 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011371 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011372 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011373 return -EINVAL;
11374 }
11375 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011376 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11377 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011378 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011379#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11380 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11381 dev, mac, params);
11382#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011383
11384 if (cds_is_sub_20_mhz_enabled()) {
11385 hdd_err("TDLS not allowed with sub 20 MHz");
11386 return -EINVAL;
11387 }
11388
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011389 StaParams.capability = params->capability;
11390 StaParams.uapsd_queues = params->uapsd_queues;
11391 StaParams.max_sp = params->max_sp;
11392
11393 /* Convert (first channel , number of channels) tuple to
11394 * the total list of channels. This goes with the assumption
11395 * that if the first channel is < 14, then the next channels
11396 * are an incremental of 1 else an incremental of 4 till the number
11397 * of channels.
11398 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011399 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011400 if (0 != params->supported_channels_len) {
11401 int i = 0, j = 0, k = 0, no_of_channels = 0;
11402 int num_unique_channels;
11403 int next;
11404 for (i = 0;
11405 i < params->supported_channels_len
11406 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11407 int wifi_chan_index;
11408 if (!wlan_hdd_is_duplicate_channel
11409 (StaParams.supported_channels, j,
11410 params->supported_channels[i])) {
11411 StaParams.
11412 supported_channels[j] =
11413 params->
11414 supported_channels[i];
11415 } else {
11416 continue;
11417 }
11418 wifi_chan_index =
11419 ((StaParams.supported_channels[j] <=
11420 HDD_CHANNEL_14) ? 1 : 4);
11421 no_of_channels =
11422 params->supported_channels[i + 1];
11423
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011424 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 -080011425 StaParams.
11426 supported_channels[j],
11427 wifi_chan_index,
11428 no_of_channels);
11429 for (k = 1; k <= no_of_channels &&
11430 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11431 k++) {
11432 next =
11433 StaParams.
11434 supported_channels[j] +
11435 wifi_chan_index;
11436 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11437 StaParams.
11438 supported_channels[j
11439 +
11440 1]
11441 = next;
11442 } else {
11443 continue;
11444 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011445 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011446 j + 1,
11447 StaParams.
11448 supported_channels[j +
11449 1]);
11450 j += 1;
11451 }
11452 }
11453 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011454 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011455 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011456 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011457 StaParams.
11458 supported_channels[i]);
11459 }
11460 if (MAX_CHANNEL < num_unique_channels)
11461 num_unique_channels = MAX_CHANNEL;
11462 StaParams.supported_channels_len =
11463 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011464 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011465 StaParams.supported_channels_len);
11466 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011467 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011468 params->supported_oper_classes,
11469 params->supported_oper_classes_len);
11470 StaParams.supported_oper_classes_len =
11471 params->supported_oper_classes_len;
11472
11473 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011474 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011475 params->ext_capab,
11476 sizeof(StaParams.extn_capability));
11477
11478 if (NULL != params->ht_capa) {
11479 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011480 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011481 sizeof(tSirHTCap));
11482 }
11483
11484 StaParams.supported_rates_len =
11485 params->supported_rates_len;
11486
11487 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11488 * The supported_rates array , for all the structures propogating till Add Sta
11489 * to the firmware has to be modified , if the supplicant (ieee80211) is
11490 * modified to send more rates.
11491 */
11492
11493 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11494 */
11495 if (StaParams.supported_rates_len >
11496 SIR_MAC_MAX_SUPP_RATES)
11497 StaParams.supported_rates_len =
11498 SIR_MAC_MAX_SUPP_RATES;
11499
11500 if (0 != StaParams.supported_rates_len) {
11501 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011502 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011503 params->supported_rates,
11504 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011505 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011506 StaParams.supported_rates_len);
11507 for (i = 0; i < StaParams.supported_rates_len;
11508 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011509 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011510 StaParams.supported_rates[i]);
11511 }
11512
11513 if (NULL != params->vht_capa) {
11514 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011515 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011516 params->vht_capa,
11517 sizeof(tSirVHTCap));
11518 }
11519
11520 if (0 != params->ext_capab_len) {
11521 /*Define A Macro : TODO Sunil */
11522 if ((1 << 4) & StaParams.extn_capability[3]) {
11523 isBufSta = 1;
11524 }
11525 /* TDLS Channel Switching Support */
11526 if ((1 << 6) & StaParams.extn_capability[3]) {
11527 isOffChannelSupported = 1;
11528 }
11529 }
11530
Nitesh Shah99934ac2016-09-05 15:54:08 +053011531 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011532 (params->ht_capa || params->vht_capa ||
11533 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011534 is_qos_wmm_sta = true;
11535
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011536 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011537 " is_qos_wmm_sta= %d HTcapPresent = %d",
11538 __func__, is_qos_wmm_sta,
11539 StaParams.htcap_present);
11540
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011542 &StaParams,
11543 isBufSta,
11544 isOffChannelSupported,
11545 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011546 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011547 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011548 return -EINVAL;
11549 }
11550
11551 status =
11552 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11553 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011554 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011555 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011556 return -EINVAL;
11557 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011558#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011559 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011560 }
11561 EXIT();
11562 return ret;
11563}
11564
11565/**
11566 * wlan_hdd_change_station() - cfg80211 change station handler function
11567 * @wiphy: Pointer to the wiphy structure
11568 * @dev: Pointer to the net device.
11569 * @mac: bssid
11570 * @params: Pointer to station parameters
11571 *
11572 * This is the cfg80211 change station handler function which invokes
11573 * the internal function @__wlan_hdd_change_station with
11574 * SSR protection.
11575 *
11576 * Return: 0 for success, error number on failure.
11577 */
11578#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11579static int wlan_hdd_change_station(struct wiphy *wiphy,
11580 struct net_device *dev,
11581 const u8 *mac,
11582 struct station_parameters *params)
11583#else
11584static int wlan_hdd_change_station(struct wiphy *wiphy,
11585 struct net_device *dev,
11586 u8 *mac,
11587 struct station_parameters *params)
11588#endif
11589{
11590 int ret;
11591
11592 cds_ssr_protect(__func__);
11593 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11594 cds_ssr_unprotect(__func__);
11595
11596 return ret;
11597}
11598
11599/*
11600 * FUNCTION: __wlan_hdd_cfg80211_add_key
11601 * This function is used to initialize the key information
11602 */
11603static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11604 struct net_device *ndev,
11605 u8 key_index, bool pairwise,
11606 const u8 *mac_addr,
11607 struct key_params *params)
11608{
11609 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11610 tCsrRoamSetKey setKey;
11611 int status;
11612 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011613 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011614 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011615 hdd_context_t *pHddCtx;
11616 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11617
11618 ENTER();
11619
Anurag Chouhan6d760662016-02-20 16:05:43 +053011620 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011621 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011622 return -EINVAL;
11623 }
11624
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011625 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011626 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011627 return -EINVAL;
11628 }
11629
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011630 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011631 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11632 pAdapter->sessionId, params->key_len));
11633 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11634 status = wlan_hdd_validate_context(pHddCtx);
11635
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011636 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011637 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011639 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011640 hdd_device_mode_to_string(pAdapter->device_mode),
11641 pAdapter->device_mode);
11642
11643 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011644 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645
11646 return -EINVAL;
11647 }
11648
11649 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011650 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011651
11652 return -EINVAL;
11653 }
11654
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011655 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011656
11657 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011658 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011659 setKey.keyId = key_index;
11660 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011661 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011662
11663 switch (params->cipher) {
11664 case WLAN_CIPHER_SUITE_WEP40:
11665 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11666 break;
11667
11668 case WLAN_CIPHER_SUITE_WEP104:
11669 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11670 break;
11671
11672 case WLAN_CIPHER_SUITE_TKIP:
11673 {
11674 u8 *pKey = &setKey.Key[0];
11675 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11676
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011677 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011678
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011679 /* Supplicant sends the 32bytes key in this order
11680 *
11681 * |--------------|----------|----------|
11682 * | Tk1 |TX-MIC | RX Mic |
11683 * |--------------|----------|----------|
11684 * <---16bytes---><--8bytes--><--8bytes-->
11685 *
11686 * Sme expects the 32 bytes key to be in the below order
11687 *
11688 * |--------------|----------|----------|
11689 * | Tk1 |RX-MIC | TX Mic |
11690 * |--------------|----------|----------|
11691 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011692 */
11693 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011694 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011695
11696 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011697 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011698
11699 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011700 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011701
11702 break;
11703 }
11704
11705 case WLAN_CIPHER_SUITE_CCMP:
11706 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11707 break;
11708
11709#ifdef FEATURE_WLAN_WAPI
11710 case WLAN_CIPHER_SUITE_SMS4:
11711 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011712 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11714 mac_addr, params->key,
11715 params->key_len);
11716 return 0;
11717 }
11718#endif
11719
11720#ifdef FEATURE_WLAN_ESE
11721 case WLAN_CIPHER_SUITE_KRK:
11722 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11723 break;
11724#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11725 case WLAN_CIPHER_SUITE_BTK:
11726 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11727 break;
11728#endif
11729#endif
11730
11731#ifdef WLAN_FEATURE_11W
11732 case WLAN_CIPHER_SUITE_AES_CMAC:
11733 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11734 break;
11735#endif
11736
11737 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011738 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011739 return -EOPNOTSUPP;
11740 }
11741
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011742 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011743
11744 if (!pairwise) {
11745 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011746 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011747 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011748 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011749 } else {
11750 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011751 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011753 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011754 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011755 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011756 /* if a key is already installed, block all subsequent ones */
11757 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011758 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011759 return 0;
11760 }
11761
11762 setKey.keyDirection = eSIR_TX_RX;
11763 /*Set the group key */
11764 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11765 pAdapter->sessionId, &setKey, &roamId);
11766
11767 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011768 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011769 return -EINVAL;
11770 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011771 /* Save the keys here and call sme_roam_set_key for setting
11772 * the PTK after peer joins the IBSS network
11773 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011774 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011775 &setKey, sizeof(tCsrRoamSetKey));
11776
11777 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11778 return status;
11779 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011780 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11781 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011782 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11783 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011784 status = wlansap_set_key_sta(
11785 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011786 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011787 hdd_err("wlansap_set_key_sta failed status: %d",
11788 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011789 }
11790 }
11791
11792 /* Save the key in ap ctx for use on START_BASS and restart */
11793 if (pairwise ||
11794 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11795 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011796 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011797 sizeof(tCsrRoamSetKey));
11798 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011799 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011800 sizeof(tCsrRoamSetKey));
11801
Krunal Sonib4326f22016-03-10 13:05:51 -080011802 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11803 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011804 hdd_wext_state_t *pWextState =
11805 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11806 hdd_station_ctx_t *pHddStaCtx =
11807 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11808
11809 if (!pairwise) {
11810 /* set group key */
11811 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011812 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011813 __func__, __LINE__);
11814 hdd_perform_roam_set_key_complete(pAdapter);
11815 }
11816 }
11817
11818 pWextState->roamProfile.Keys.KeyLength[key_index] =
11819 (u8) params->key_len;
11820
11821 pWextState->roamProfile.Keys.defaultIndex = key_index;
11822
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011823 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011824 KeyMaterial[key_index][0], params->key,
11825 params->key_len);
11826
11827 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11828
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011829 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011830 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11831 setKey.keyDirection);
11832
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011833 /* The supplicant may attempt to set the PTK once
11834 * pre-authentication is done. Save the key in the
11835 * UMAC and include it in the ADD BSS request
11836 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011837 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011838 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011839 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011840 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011841 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011842 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011843 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011844 return -EINVAL;
11845 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011846
11847 /* issue set key request to SME */
11848 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11849 pAdapter->sessionId, &setKey, &roamId);
11850
11851 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011852 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011853 pHddStaCtx->roam_info.roamingState =
11854 HDD_ROAM_STATE_NONE;
11855 return -EINVAL;
11856 }
11857
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011858 /* in case of IBSS as there was no information
11859 * available about WEP keys during IBSS join, group
11860 * key intialized with NULL key, so re-initialize
11861 * group key with correct value
11862 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011863 if ((eCSR_BSS_TYPE_START_IBSS ==
11864 pWextState->roamProfile.BSSType)
11865 &&
11866 !((IW_AUTH_KEY_MGMT_802_1X ==
11867 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11868 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11869 pHddStaCtx->conn_info.authType)
11870 )
11871 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11872 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11873 )
11874 ) {
11875 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011876 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011877
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011878 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011879 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11880 setKey.keyDirection);
11881
11882 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11883 pAdapter->sessionId, &setKey,
11884 &roamId);
11885
11886 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011887 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011888 pHddStaCtx->roam_info.roamingState =
11889 HDD_ROAM_STATE_NONE;
11890 return -EINVAL;
11891 }
11892 }
11893 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011894 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011895 return 0;
11896}
11897
11898static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11899 struct net_device *ndev,
11900 u8 key_index, bool pairwise,
11901 const u8 *mac_addr,
11902 struct key_params *params)
11903{
11904 int ret;
11905 cds_ssr_protect(__func__);
11906 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11907 mac_addr, params);
11908 cds_ssr_unprotect(__func__);
11909
11910 return ret;
11911}
11912
11913/*
11914 * FUNCTION: __wlan_hdd_cfg80211_get_key
11915 * This function is used to get the key information
11916 */
11917static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11918 struct net_device *ndev,
11919 u8 key_index, bool pairwise,
11920 const u8 *mac_addr, void *cookie,
11921 void (*callback)(void *cookie,
11922 struct key_params *)
11923 )
11924{
11925 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11926 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11927 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11928 struct key_params params;
11929
11930 ENTER();
11931
Anurag Chouhan6d760662016-02-20 16:05:43 +053011932 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011933 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011934 return -EINVAL;
11935 }
11936
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011937 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011938 hdd_device_mode_to_string(pAdapter->device_mode),
11939 pAdapter->device_mode);
11940
11941 memset(&params, 0, sizeof(params));
11942
11943 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011944 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011945 return -EINVAL;
11946 }
11947
11948 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11949 case eCSR_ENCRYPT_TYPE_NONE:
11950 params.cipher = IW_AUTH_CIPHER_NONE;
11951 break;
11952
11953 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11954 case eCSR_ENCRYPT_TYPE_WEP40:
11955 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11956 break;
11957
11958 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11959 case eCSR_ENCRYPT_TYPE_WEP104:
11960 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11961 break;
11962
11963 case eCSR_ENCRYPT_TYPE_TKIP:
11964 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11965 break;
11966
11967 case eCSR_ENCRYPT_TYPE_AES:
11968 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11969 break;
11970
11971 default:
11972 params.cipher = IW_AUTH_CIPHER_NONE;
11973 break;
11974 }
11975
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011976 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011977 TRACE_CODE_HDD_CFG80211_GET_KEY,
11978 pAdapter->sessionId, params.cipher));
11979
11980 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11981 params.seq_len = 0;
11982 params.seq = NULL;
11983 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11984 callback(cookie, &params);
11985
11986 EXIT();
11987 return 0;
11988}
11989
11990static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11991 struct net_device *ndev,
11992 u8 key_index, bool pairwise,
11993 const u8 *mac_addr, void *cookie,
11994 void (*callback)(void *cookie,
11995 struct key_params *)
11996 )
11997{
11998 int ret;
11999
12000 cds_ssr_protect(__func__);
12001 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12002 mac_addr, cookie, callback);
12003 cds_ssr_unprotect(__func__);
12004
12005 return ret;
12006}
12007
12008/**
12009 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12010 * @wiphy: wiphy interface context
12011 * @ndev: pointer to net device
12012 * @key_index: Key index used in 802.11 frames
12013 * @unicast: true if it is unicast key
12014 * @multicast: true if it is multicast key
12015 *
12016 * This function is required for cfg80211_ops API.
12017 * It is used to delete the key information
12018 * Underlying hardware implementation does not have API to delete the
12019 * encryption key. It is automatically deleted when the peer is
12020 * removed. Hence this function currently does nothing.
12021 * Future implementation may interprete delete key operation to
12022 * replacing the key with a random junk value, effectively making it
12023 * useless.
12024 *
12025 * Return: status code, always 0.
12026 */
12027
12028static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12029 struct net_device *ndev,
12030 u8 key_index,
12031 bool pairwise, const u8 *mac_addr)
12032{
12033 EXIT();
12034 return 0;
12035}
12036
12037/**
12038 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12039 * @wiphy: Pointer to wiphy structure.
12040 * @dev: Pointer to net_device structure.
12041 * @key_index: key index
12042 * @pairwise: pairwise
12043 * @mac_addr: mac address
12044 *
12045 * This is the cfg80211 delete key handler function which invokes
12046 * the internal function @__wlan_hdd_cfg80211_del_key with
12047 * SSR protection.
12048 *
12049 * Return: 0 for success, error number on failure.
12050 */
12051static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12052 struct net_device *dev,
12053 u8 key_index,
12054 bool pairwise, const u8 *mac_addr)
12055{
12056 int ret;
12057
12058 cds_ssr_protect(__func__);
12059 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12060 pairwise, mac_addr);
12061 cds_ssr_unprotect(__func__);
12062
12063 return ret;
12064}
12065
12066/*
12067 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12068 * This function is used to set the default tx key index
12069 */
12070static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12071 struct net_device *ndev,
12072 u8 key_index,
12073 bool unicast, bool multicast)
12074{
12075 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12076 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12077 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12078 hdd_context_t *pHddCtx;
12079 int status;
12080
12081 ENTER();
12082
Anurag Chouhan6d760662016-02-20 16:05:43 +053012083 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012084 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012085 return -EINVAL;
12086 }
12087
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012088 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012089 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012090 return -EINVAL;
12091 }
12092
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012093 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012094 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12095 pAdapter->sessionId, key_index));
12096
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012097 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012098 hdd_device_mode_to_string(pAdapter->device_mode),
12099 pAdapter->device_mode, key_index);
12100
12101 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012102 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012103 return -EINVAL;
12104 }
12105
12106 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12107 status = wlan_hdd_validate_context(pHddCtx);
12108
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012109 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012110 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012111
Krunal Sonib4326f22016-03-10 13:05:51 -080012112 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12113 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012114 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12115 pHddStaCtx->conn_info.ucEncryptionType) &&
12116 (eCSR_ENCRYPT_TYPE_AES !=
12117 pHddStaCtx->conn_info.ucEncryptionType)) {
12118 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012119 * then update the default key index
12120 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012121
12122 tCsrRoamSetKey setKey;
12123 uint32_t roamId = 0xFF;
12124 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12125
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012126 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012127
12128 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012129 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012130 setKey.keyId = key_index;
12131 setKey.keyLength = Keys->KeyLength[key_index];
12132
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012133 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012134 &Keys->KeyMaterial[key_index][0],
12135 Keys->KeyLength[key_index]);
12136
12137 setKey.keyDirection = eSIR_TX_RX;
12138
Anurag Chouhanc5548422016-02-24 18:33:27 +053012139 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012140 &pHddStaCtx->conn_info.bssId);
12141
12142 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12143 pWextState->roamProfile.EncryptionType.
12144 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012145 /* In the case of dynamic wep
12146 * supplicant hardcodes DWEP type to
12147 * eCSR_ENCRYPT_TYPE_WEP104 even
12148 * though ap is configured for WEP-40
12149 * encryption. In this canse the key
12150 * length is 5 but the encryption type
12151 * is 104 hence checking the key
12152 * lenght(5) and encryption type(104)
12153 * and switching encryption type to 40
12154 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012155 pWextState->roamProfile.EncryptionType.
12156 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12157 pWextState->roamProfile.mcEncryptionType.
12158 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12159 }
12160
12161 setKey.encType =
12162 pWextState->roamProfile.EncryptionType.
12163 encryptionType[0];
12164
12165 /* Issue set key request */
12166 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12167 pAdapter->sessionId, &setKey,
12168 &roamId);
12169
12170 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012171 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012172 status);
12173 return -EINVAL;
12174 }
12175 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012176 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012177 /* In SoftAp mode setting key direction for default mode */
12178 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12179 pWextState->roamProfile.EncryptionType.encryptionType[0])
12180 && (eCSR_ENCRYPT_TYPE_AES !=
12181 pWextState->roamProfile.EncryptionType.
12182 encryptionType[0])) {
12183 /* Saving key direction for default key index to TX default */
12184 hdd_ap_ctx_t *pAPCtx =
12185 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12186 pAPCtx->wepKey[key_index].keyDirection =
12187 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012188 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012189 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012190 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012191 }
12192 }
12193
12194 EXIT();
12195 return status;
12196}
12197
12198static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12199 struct net_device *ndev,
12200 u8 key_index,
12201 bool unicast, bool multicast)
12202{
12203 int ret;
12204 cds_ssr_protect(__func__);
12205 ret =
12206 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12207 multicast);
12208 cds_ssr_unprotect(__func__);
12209
12210 return ret;
12211}
12212
Abhishek Singhc9941602016-08-09 16:06:22 +053012213/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012214 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12215 * interface that BSS might have been lost.
12216 * @pAdapter: adaptor
12217 * @bssid: bssid which might have been lost
12218 *
12219 * Return: bss which is unlinked from kernel cache
12220 */
12221struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12222 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012223{
12224 struct net_device *dev = pAdapter->dev;
12225 struct wireless_dev *wdev = dev->ieee80211_ptr;
12226 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012227 struct cfg80211_bss *bss = NULL;
12228
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012229 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012230 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012231 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012232 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012233 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012234 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012235 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012236 cfg80211_unlink_bss(wiphy, bss);
12237 }
12238 return bss;
12239}
12240
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012241#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12242 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12243static struct cfg80211_bss *
12244wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12245 struct ieee80211_channel *chan,
12246 struct ieee80211_mgmt *mgmt,
12247 size_t frame_len,
12248 int rssi, gfp_t gfp,
12249 uint64_t boottime_ns)
12250{
12251 struct cfg80211_bss *bss_status = NULL;
12252 struct cfg80211_inform_bss data = {0};
12253
12254 data.chan = chan;
12255 data.boottime_ns = boottime_ns;
12256 data.signal = rssi;
12257 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12258 frame_len, gfp);
12259 return bss_status;
12260}
12261#else
12262static struct cfg80211_bss *
12263wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12264 struct ieee80211_channel *chan,
12265 struct ieee80211_mgmt *mgmt,
12266 size_t frame_len,
12267 int rssi, gfp_t gfp,
12268 uint64_t boottime_ns)
12269{
12270 struct cfg80211_bss *bss_status = NULL;
12271
12272 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12273 rssi, gfp);
12274 return bss_status;
12275}
12276#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278/**
12279 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12280 * @pAdapter: Pointer to adapter
12281 * @bss_desc: Pointer to bss descriptor
12282 *
12283 * This function is used to inform the BSS details to nl80211 interface.
12284 *
12285 * Return: struct cfg80211_bss pointer
12286 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012287struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12288 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012289{
12290 /*
12291 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12292 * already exists in bss data base of cfg80211 for that particular BSS
12293 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12294 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12295 * As of now there is no possibility to get the mgmt(probe response)
12296 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12297 * and passing to cfg80211_inform_bss_frame.
12298 */
12299 struct net_device *dev = pAdapter->dev;
12300 struct wireless_dev *wdev = dev->ieee80211_ptr;
12301 struct wiphy *wiphy = wdev->wiphy;
12302 int chan_no = bss_desc->channelId;
12303#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12304 qcom_ie_age *qie_age = NULL;
12305 int ie_length =
12306 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12307#else
12308 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12309#endif
12310 const char *ie =
12311 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12312 unsigned int freq;
12313 struct ieee80211_channel *chan;
12314 struct ieee80211_mgmt *mgmt = NULL;
12315 struct cfg80211_bss *bss_status = NULL;
12316 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12317 int rssi = 0;
12318 hdd_context_t *pHddCtx;
12319 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012321 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012322
12323 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12324 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012325 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012326 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012327
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012328 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012329 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012330 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012331 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012332 return NULL;
12333 }
12334
12335 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12336
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012337 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012338 * Instead it wants a monotonic increasing value
12339 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012340 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012341 mgmt->u.probe_resp.timestamp =
12342 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343
12344 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12345 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12346
12347#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12348 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12349 /* Assuming this is the last IE, copy at the end */
12350 ie_length -= sizeof(qcom_ie_age);
12351 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12352 qie_age->element_id = QCOM_VENDOR_IE_ID;
12353 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12354 qie_age->oui_1 = QCOM_OUI1;
12355 qie_age->oui_2 = QCOM_OUI2;
12356 qie_age->oui_3 = QCOM_OUI3;
12357 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012358 /*
12359 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12360 * all bss related timestamp is in units of ms. Due to this when scan
12361 * results are sent to lowi the scan age is high.To address this,
12362 * send age in units of 1/10 ms.
12363 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012364 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012365 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012366 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012367 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12368 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012369 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12370 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012371#endif
12372
12373 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12374 if (bss_desc->fProbeRsp) {
12375 mgmt->frame_control |=
12376 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12377 } else {
12378 mgmt->frame_control |=
12379 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12380 }
12381
12382 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012383 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012384 freq =
12385 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012386 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012387 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012388 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012389 freq =
12390 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012391 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012392 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012393 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012394 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012395 return NULL;
12396 }
12397
12398 chan = __ieee80211_get_channel(wiphy, freq);
12399 /* When the band is changed on the fly using the GUI, three things are done
12400 * 1. scan abort
12401 * 2. flush scan results from cache
12402 * 3. update the band with the new band user specified (refer to the
12403 * hdd_set_band_helper function) as part of the scan abort, message will be
12404 * queued to PE and we proceed with flushing and changinh the band.
12405 * PE will stop the scanning further and report back the results what ever
12406 * it had till now by calling the call back function.
12407 * if the time between update band and scandone call back is sufficient
12408 * enough the band change reflects in SME, SME validates the channels
12409 * and discards the channels correponding to previous band and calls back
12410 * with zero bss results. but if the time between band update and scan done
12411 * callback is very small then band change will not reflect in SME and SME
12412 * reports to HDD all the channels correponding to previous band.this is due
12413 * to race condition.but those channels are invalid to the new band and so
12414 * this function __ieee80211_get_channel will return NULL.Each time we
12415 * report scan result with this pointer null warning kernel trace is printed.
12416 * if the scan results contain large number of APs continuosly kernel
12417 * warning trace is printed and it will lead to apps watch dog bark.
12418 * So drop the bss and continue to next bss.
12419 */
12420 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012421 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12422 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012423 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012424 return NULL;
12425 }
12426
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012427 /* Based on .ini configuration, raw rssi can be reported for bss.
12428 * Raw rssi is typically used for estimating power.
12429 */
12430
12431 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12432 bss_desc->rssi;
12433
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012434 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012435 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012436
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012437 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012438 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012439 (int)(rssi / 100),
12440 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012441
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012442 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12443 frame_len, rssi,
12444 GFP_KERNEL,
12445 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012446 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012447 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012448 return bss_status;
12449}
12450
12451/**
12452 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12453 * @pAdapter: Pointer to adapter
12454 * @pRoamInfo: Pointer to roam info
12455 *
12456 * This function is used to update the BSS data base of CFG8011
12457 *
12458 * Return: struct cfg80211_bss pointer
12459 */
12460struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12461 tCsrRoamInfo *pRoamInfo)
12462{
12463 tCsrRoamConnectedProfile roamProfile;
12464 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12465 struct cfg80211_bss *bss = NULL;
12466
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012467 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12468 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12469
12470 if (NULL != roamProfile.pBssDesc) {
12471 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12472 roamProfile.pBssDesc);
12473
12474 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012475 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012476
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012477 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012478 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012479 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012481 return bss;
12482}
12483/**
12484 * wlan_hdd_cfg80211_update_bss() - update bss
12485 * @wiphy: Pointer to wiphy
12486 * @pAdapter: Pointer to adapter
12487 * @scan_time: scan request timestamp
12488 *
12489 * Return: zero if success, non-zero otherwise
12490 */
12491int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12492 hdd_adapter_t *pAdapter,
12493 uint32_t scan_time)
12494{
12495 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12496 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012497 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012498 tScanResultHandle pResult;
12499 struct cfg80211_bss *bss_status = NULL;
12500 hdd_context_t *pHddCtx;
12501 int ret;
12502
12503 ENTER();
12504
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012505 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12506 hdd_err("invalid session id: %d", pAdapter->sessionId);
12507 return -EINVAL;
12508 }
12509
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012510 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012511 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12512 NO_SESSION, pAdapter->sessionId));
12513
12514 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12515 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012516 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012517 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012518
12519 /* start getting scan results and populate cgf80211 BSS database */
12520 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12521
12522 /* no scan results */
12523 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012524 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012525 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012526 }
12527
12528 pScanResult = sme_scan_result_get_first(hHal, pResult);
12529
12530 while (pScanResult) {
12531 /*
12532 * - cfg80211_inform_bss() is not updating ie field of bss
12533 * entry if entry already exists in bss data base of cfg80211
12534 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12535 * to update thebss entry instead of cfg80211_inform_bss,
12536 * But this call expects mgmt packet as input. As of now
12537 * there is no possibility to get the mgmt(probe response)
12538 * frame from PE, converting bss_desc to
12539 * ieee80211_mgmt(probe response) and passing to c
12540 * fg80211_inform_bss_frame.
12541 * - Update BSS only if beacon timestamp is later than
12542 * scan request timestamp.
12543 */
12544 if ((scan_time == 0) ||
12545 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012546 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012547 bss_status =
12548 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12549 &pScanResult->BssDescriptor);
12550
12551 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012552 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012553 } else {
12554 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012556 bss_status);
12557 }
12558 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012559 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012560 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12561 }
12562 pScanResult = sme_scan_result_get_next(hHal, pResult);
12563 }
12564
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012565 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012566 /*
12567 * For SAP mode, scan is invoked by hostapd during SAP start
12568 * if hostapd is restarted, we need to flush previous scan
12569 * result so that it will reflect environment change
12570 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012571 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012572#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12573 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12574#endif
12575 )
12576 sme_scan_flush_result(hHal);
12577
12578 EXIT();
12579 return 0;
12580}
12581
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012582/**
12583 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12584 * @pAdapter: Pointer to adapter
12585 * @pRoamInfo: Pointer to roam info
12586 * @index: Index
12587 * @preauth: Preauth flag
12588 *
12589 * This function is used to notify the supplicant of a new PMKSA candidate.
12590 *
12591 * Return: 0 for success, non-zero for failure
12592 */
12593int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12594 tCsrRoamInfo *pRoamInfo,
12595 int index, bool preauth)
12596{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012597 struct net_device *dev = pAdapter->dev;
12598 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12599
12600 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012601 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012602
12603 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012604 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012605 return -EINVAL;
12606 }
12607
12608 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012609 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012610 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12611 cfg80211_pmksa_candidate_notify(dev, index,
12612 pRoamInfo->bssid.bytes,
12613 preauth, GFP_KERNEL);
12614 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012615 return 0;
12616}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617
12618#ifdef FEATURE_WLAN_LFR_METRICS
12619/**
12620 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12621 * @pAdapter: Pointer to adapter
12622 * @pRoamInfo: Pointer to roam info
12623 *
12624 * 802.11r/LFR metrics reporting function to report preauth initiation
12625 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012626 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012627 */
12628#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012629QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012630 tCsrRoamInfo *pRoamInfo)
12631{
12632 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12633 union iwreq_data wrqu;
12634
12635 ENTER();
12636
12637 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012638 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012639 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012640 }
12641
12642 /* create the event */
12643 memset(&wrqu, 0, sizeof(wrqu));
12644 memset(metrics_notification, 0, sizeof(metrics_notification));
12645
12646 wrqu.data.pointer = metrics_notification;
12647 wrqu.data.length = scnprintf(metrics_notification,
12648 sizeof(metrics_notification),
12649 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12650 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12651
12652 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12653 metrics_notification);
12654
12655 EXIT();
12656
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012657 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012658}
12659
12660/**
12661 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12662 * @pAdapter: Pointer to adapter
12663 * @pRoamInfo: Pointer to roam info
12664 * @preauth_status: Preauth status
12665 *
12666 * 802.11r/LFR metrics reporting function to report handover initiation
12667 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012668 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012669 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012670QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12672 tCsrRoamInfo *pRoamInfo,
12673 bool preauth_status)
12674{
12675 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12676 union iwreq_data wrqu;
12677
12678 ENTER();
12679
12680 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012681 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012682 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012683 }
12684
12685 /* create the event */
12686 memset(&wrqu, 0, sizeof(wrqu));
12687 memset(metrics_notification, 0, sizeof(metrics_notification));
12688
12689 scnprintf(metrics_notification, sizeof(metrics_notification),
12690 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12691 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12692
12693 if (1 == preauth_status)
12694 strlcat(metrics_notification, " true",
12695 sizeof(metrics_notification));
12696 else
12697 strlcat(metrics_notification, " false",
12698 sizeof(metrics_notification));
12699
12700 wrqu.data.pointer = metrics_notification;
12701 wrqu.data.length = strlen(metrics_notification);
12702
12703 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12704 metrics_notification);
12705
12706 EXIT();
12707
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012708 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012709}
12710
12711/**
12712 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12713 * @pAdapter: Pointer to adapter
12714 * @pRoamInfo: Pointer to roam info
12715 *
12716 * 802.11r/LFR metrics reporting function to report handover initiation
12717 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012718 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012719 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012720QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012721 tCsrRoamInfo *pRoamInfo)
12722{
12723 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12724 union iwreq_data wrqu;
12725
12726 ENTER();
12727
12728 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012729 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012730 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012731 }
12732
12733 /* create the event */
12734 memset(&wrqu, 0, sizeof(wrqu));
12735 memset(metrics_notification, 0, sizeof(metrics_notification));
12736
12737 wrqu.data.pointer = metrics_notification;
12738 wrqu.data.length = scnprintf(metrics_notification,
12739 sizeof(metrics_notification),
12740 "QCOM: LFR_PREAUTH_HANDOVER "
12741 MAC_ADDRESS_STR,
12742 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12743
12744 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12745 metrics_notification);
12746
12747 EXIT();
12748
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012749 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012750}
12751#endif
12752
12753/**
12754 * hdd_select_cbmode() - select channel bonding mode
12755 * @pAdapter: Pointer to adapter
12756 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012757 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012758 *
12759 * Return: none
12760 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012761void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080012762 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012763{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012764 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012765 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012766 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012767
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012768 /*
12769 * CDS api expects secondary channel for calculating
12770 * the channel params
12771 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012772 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012773 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12774 if (operationChannel >= 1 && operationChannel <= 5)
12775 sec_ch = operationChannel + 4;
12776 else if (operationChannel >= 6 && operationChannel <= 13)
12777 sec_ch = operationChannel - 4;
12778 }
12779
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012780 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012781 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012782
12783 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012784 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012785 uint8_t iniDot11Mode =
12786 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12787
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012788 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012789 switch (iniDot11Mode) {
12790 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012791 case eHDD_DOT11_MODE_11ax:
12792 case eHDD_DOT11_MODE_11ax_ONLY:
12793 if (sme_is_feature_supported_by_fw(DOT11AX))
12794 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12795 else if (sme_is_feature_supported_by_fw(DOT11AC))
12796 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12797 else
12798 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12799 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012800 case eHDD_DOT11_MODE_11ac:
12801 case eHDD_DOT11_MODE_11ac_ONLY:
12802 if (sme_is_feature_supported_by_fw(DOT11AC))
12803 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12804 else
12805 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12806 break;
12807 case eHDD_DOT11_MODE_11n:
12808 case eHDD_DOT11_MODE_11n_ONLY:
12809 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12810 break;
12811 default:
12812 hdd_dot11_mode = iniDot11Mode;
12813 break;
12814 }
12815 ch_info->channel_width = ch_params->ch_width;
12816 ch_info->phy_mode =
12817 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012818 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012819 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012820 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012821 ch_info->channel_width, ch_info->phy_mode,
12822 ch_info->channel);
12823 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012824}
12825
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012826/**
12827 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12828 * @adapter: STA adapter
12829 * @roam_profile: STA roam profile
12830 *
12831 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12832 *
12833 * Return: false if sta-sap conc is not allowed, else return true
12834 */
12835static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12836 tCsrRoamProfile *roam_profile)
12837{
12838 hdd_context_t *hdd_ctx;
12839 hdd_adapter_t *ap_adapter;
12840 hdd_ap_ctx_t *hdd_ap_ctx;
12841 hdd_hostapd_state_t *hostapd_state;
12842 uint8_t channel = 0;
12843 QDF_STATUS status;
12844
12845 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12846 if (!hdd_ctx) {
12847 hdd_err("HDD context is NULL");
12848 return true;
12849 }
12850
12851 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12852 /* probably no sap running, no handling required */
12853 if (ap_adapter == NULL)
12854 return true;
12855
12856 /*
12857 * sap is not in started state, so it is fine to go ahead with sta.
12858 * if sap is currently doing CAC then don't allow sta to go further.
12859 */
12860 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12861 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12862 return true;
12863
12864 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12865 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12866 return false;
12867 }
12868
12869 /*
12870 * log and return error, if we allow STA to go through, we don't
12871 * know what is going to happen better stop sta connection
12872 */
12873 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12874 if (NULL == hdd_ap_ctx) {
12875 hdd_err("AP context not found");
12876 return false;
12877 }
12878
12879 /* sap is on non-dfs channel, nothing to handle */
12880 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012881 hdd_debug("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012882 return true;
12883 }
12884 /*
12885 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012886 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012887 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012888 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012889 roam_profile, &channel);
12890
Nitesh Shah59774522016-09-16 15:14:21 +053012891 /*
12892 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12893 * channels for roaming case.
12894 */
12895 if (CDS_IS_CHANNEL_24GHZ(channel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012896 hdd_debug("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012897 return true;
12898 }
12899
12900 /*
12901 * If channel is 0 or DFS then better to call pcl and find out the
12902 * best channel. If channel is non-dfs 5 GHz then better move SAP
12903 * to STA's channel to make scc, so we have room for 3port MCC
12904 * scenario.
12905 */
12906 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012907 channel = policy_mgr_get_nondfs_preferred_channel(
12908 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012909
12910 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12911 qdf_event_reset(&hostapd_state->qdf_event);
12912 status = wlansap_set_channel_change_with_csa(
12913 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12914 hdd_ap_ctx->sapConfig.ch_width_orig);
12915
12916 if (QDF_STATUS_SUCCESS != status) {
12917 hdd_err("Set channel with CSA IE failed, can't allow STA");
12918 return false;
12919 }
12920
12921 /*
12922 * wait here for SAP to finish the channel switch. When channel
12923 * switch happens, SAP sends few beacons with CSA_IE. After
12924 * successfully Transmission of those beacons, it will move its
12925 * state from started to disconnected and move to new channel.
12926 * once it moves to new channel, sap again moves its state
12927 * machine from disconnected to started and set this event.
12928 * wait for 10 secs to finish this.
12929 */
12930 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12931 if (!QDF_IS_STATUS_SUCCESS(status)) {
12932 hdd_err("wait for qdf_event failed, STA not allowed!!");
12933 return false;
12934 }
12935
12936 return true;
12937}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012938
Abhishek Singhcfb44482017-03-10 12:42:37 +053012939#ifdef WLAN_FEATURE_11W
12940/**
12941 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12942 * @roam_profile: pointer to roam profile
12943 *
12944 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12945 * or pmf=2 is an explicit configuration in the supplicant
12946 * configuration, drop the connection request.
12947 *
12948 * Return: 0 if check result is valid, otherwise return error code
12949 */
12950static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12951{
12952 if (roam_profile->MFPEnabled &&
12953 !(roam_profile->MFPRequired ||
12954 roam_profile->MFPCapable)) {
12955 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12956 roam_profile->MFPEnabled,
12957 roam_profile->MFPRequired,
12958 roam_profile->MFPCapable);
12959 return -EINVAL;
12960 }
12961 return 0;
12962}
12963#else
12964static inline
12965int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12966{
12967 return 0;
12968}
12969#endif
12970
Krunal Soni31949422016-07-29 17:17:53 -070012971/**
12972 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012973 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012974 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012975 * @ssid_len: Length of ssid
12976 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012977 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012978 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012979 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012980 *
12981 * This function is used to start the association process
12982 *
12983 * Return: 0 for success, non-zero for failure
12984 */
Krunal Soni31949422016-07-29 17:17:53 -070012985static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012986 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012987 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012988 u8 operatingChannel,
12989 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012990{
12991 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012992 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012993 hdd_wext_state_t *pWextState;
12994 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012995 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012996 uint32_t roamId;
12997 tCsrRoamProfile *pRoamProfile;
12998 eCsrAuthType RSNAuthType;
12999 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013000 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013001
13002 ENTER();
13003
13004 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13005 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013006 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013007
13008 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013009 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013010 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013011
13012 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013013 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013014 status = -EINVAL;
13015 goto ret_status;
13016 }
13017
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013018 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013019 hdd_err("Connection refused: conn in progress");
13020 status = -EINVAL;
13021 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013022 }
13023
Nitesh Shah273e4e52017-04-03 12:53:36 +053013024 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13025
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013026 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013027 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13028 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013029
13030 if (pRoamProfile) {
13031 hdd_station_ctx_t *pHddStaCtx;
13032 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13033
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013034 /* Restart the opportunistic timer
13035 *
13036 * If hw_mode_change_in_progress is true, then wait
13037 * till firmware sends the callback for hw_mode change.
13038 *
13039 * Else set connect_in_progress as true and proceed.
13040 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013041 policy_mgr_restart_opportunistic_timer(
13042 pHddCtx->hdd_psoc, false);
13043 if (policy_mgr_is_hw_mode_change_in_progress(
13044 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013045 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013046 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013047 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013048 hdd_err("qdf wait for event failed!!");
13049 status = -EINVAL;
13050 goto ret_status;
13051 }
13052 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013053 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013054
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013055 if (HDD_WMM_USER_MODE_NO_QOS ==
13056 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13057 /*QoS not enabled in cfg file */
13058 pRoamProfile->uapsd_mask = 0;
13059 } else {
13060 /*QoS enabled, update uapsd mask from cfg file */
13061 pRoamProfile->uapsd_mask =
13062 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13063 }
13064
13065 pRoamProfile->SSIDs.numOfSSIDs = 1;
13066 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013067 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013068 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013069 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013070 ssid, ssid_len);
13071
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013072 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013073 /* cleanup bssid hint */
13074 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13075 QDF_MAC_ADDR_SIZE);
13076 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13077 QDF_MAC_ADDR_SIZE);
13078
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013079 if (bssid) {
13080 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013081 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013082 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013083 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013084 /*
13085 * Save BSSID in seperate variable as
13086 * pRoamProfile's BSSID is getting zeroed out in the
13087 * association process. In case of join failure
13088 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013089 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013090 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013091 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013092 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013093 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013094 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13095 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013096 /*
13097 * Save BSSID in a separate variable as
13098 * pRoamProfile's BSSID is getting zeroed out in the
13099 * association process. In case of join failure
13100 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013101 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013102 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013103 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013104 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013105 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013106 }
13107
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013108 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109 pRoamProfile->SSIDs.SSIDList->SSID.length,
13110 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13111 operatingChannel);
13112
13113 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13114 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013115 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013116 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13117 }
13118#ifdef FEATURE_WLAN_WAPI
13119 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013120 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013121 switch (pAdapter->wapi_info.wapiAuthMode) {
13122 case WAPI_AUTH_MODE_PSK:
13123 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013124 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013125 pAdapter->wapi_info.wapiAuthMode);
13126 pRoamProfile->AuthType.authType[0] =
13127 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13128 break;
13129 }
13130 case WAPI_AUTH_MODE_CERT:
13131 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013132 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013133 pAdapter->wapi_info.wapiAuthMode);
13134 pRoamProfile->AuthType.authType[0] =
13135 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13136 break;
13137 }
13138 } /* End of switch */
13139 if (pAdapter->wapi_info.wapiAuthMode ==
13140 WAPI_AUTH_MODE_PSK
13141 || pAdapter->wapi_info.wapiAuthMode ==
13142 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013143 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013144 pRoamProfile->AuthType.numEntries = 1;
13145 pRoamProfile->EncryptionType.numEntries = 1;
13146 pRoamProfile->EncryptionType.encryptionType[0] =
13147 eCSR_ENCRYPT_TYPE_WPI;
13148 pRoamProfile->mcEncryptionType.numEntries = 1;
13149 pRoamProfile->mcEncryptionType.
13150 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13151 }
13152 }
Krunal Soni31949422016-07-29 17:17:53 -070013153#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013154 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013155 pRoamProfile->csrPersona = pAdapter->device_mode;
13156
13157 if (operatingChannel) {
13158 pRoamProfile->ChannelInfo.ChannelList =
13159 &operatingChannel;
13160 pRoamProfile->ChannelInfo.numOfChannels = 1;
13161 } else {
13162 pRoamProfile->ChannelInfo.ChannelList = NULL;
13163 pRoamProfile->ChannelInfo.numOfChannels = 0;
13164 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013165 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013166 && operatingChannel) {
13167 /*
13168 * Need to post the IBSS power save parameters
13169 * to WMA. WMA will configure this parameters
13170 * to firmware if power save is enabled by the
13171 * firmware.
13172 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013173 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013174
Abhishek Singh471652b2017-04-14 12:28:32 +053013175 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013176 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013177 status = -EINVAL;
13178 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013179 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013180 pRoamProfile->ch_params.ch_width =
13181 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013182 /*
13183 * In IBSS mode while operating in 2.4 GHz,
13184 * the device supports only 20 MHz.
13185 */
13186 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13187 pRoamProfile->ch_params.ch_width =
13188 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013189 hdd_select_cbmode(pAdapter, operatingChannel,
13190 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013191 }
13192
Abhishek Singhcfb44482017-03-10 12:42:37 +053013193 if (wlan_hdd_cfg80211_check_pmf_valid(
13194 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013195 status = -EINVAL;
13196 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013197 }
13198
Krunal Soni31949422016-07-29 17:17:53 -070013199 /*
13200 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013201 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013202 * enhancements, the supplicant is not issuing the scan command
13203 * now. So the unicast frames which are sent from the host are
13204 * not having the additional IEs. If it is P2P CLIENT and there
13205 * is no additional IE present in roamProfile, then use the
13206 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013207 */
13208
Krunal Sonib4326f22016-03-10 13:05:51 -080013209 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013210 (!pRoamProfile->pAddIEScan)) {
13211 pRoamProfile->pAddIEScan =
13212 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13213 pRoamProfile->nAddIEScanLength =
13214 pAdapter->scan_info.scanAddIE.length;
13215 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013216
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013217 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13218 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013219 pRoamProfile))) {
13220 hdd_err("sap-sta conc will fail, can't allow sta");
13221 hdd_conn_set_connection_state(pAdapter,
13222 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013223 status = -ENOMEM;
13224 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013225 }
13226
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013227 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013228 if (!sme_config) {
13229 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013230 hdd_conn_set_connection_state(pAdapter,
13231 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013232 status = -ENOMEM;
13233 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013234 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013235 sme_get_config_param(pHddCtx->hHal, sme_config);
13236 /* These values are not sessionized. So, any change in these SME
13237 * configs on an older or parallel interface will affect the
13238 * cb mode. So, restoring the default INI params before starting
13239 * interfaces such as sta, cli etc.,
13240 */
13241 sme_config->csrConfig.channelBondingMode5GHz =
13242 pHddCtx->config->nChannelBondingMode5GHz;
13243 sme_config->csrConfig.channelBondingMode24GHz =
13244 pHddCtx->config->nChannelBondingMode24GHz;
13245 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013246 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013247 /*
13248 * Change conn_state to connecting before sme_roam_connect(),
13249 * because sme_roam_connect() has a direct path to call
13250 * hdd_sme_roam_callback(), which will change the conn_state
13251 * If direct path, conn_state will be accordingly changed to
13252 * NotConnected or Associated by either
13253 * hdd_association_completion_handler() or
13254 * hdd_dis_connect_handler() in sme_RoamCallback()if
13255 * sme_RomConnect is to be queued,
13256 * Connecting state will remain until it is completed.
13257 *
13258 * If connection state is not changed, connection state will
13259 * remain in eConnectionState_NotConnected state.
13260 * In hdd_association_completion_handler, "hddDisconInProgress"
13261 * is set to true if conn state is
13262 * eConnectionState_NotConnected.
13263 * If "hddDisconInProgress" is set to true then cfg80211 layer
13264 * is not informed of connect result indication which
13265 * is an issue.
13266 */
13267 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013268 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013269 hdd_conn_set_connection_state(pAdapter,
13270 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013271
Komal Seelama89be8d2016-09-29 11:09:26 +053013272 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13273 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013274 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013275 pAdapter->sessionId, pRoamProfile,
13276 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013277 if (QDF_IS_STATUS_ERROR(qdf_status))
13278 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013279
Rajeev Kumard31e1542017-01-13 14:37:42 -080013280 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013281 (QDF_STA_MODE == pAdapter->device_mode ||
13282 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013283 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013284 "qdf_status %d. -> NotConnected",
13285 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013286 /* change back to NotAssociated */
13287 hdd_conn_set_connection_state(pAdapter,
13288 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013289 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13290 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013291 }
13292
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013293 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013294 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013296 pRoamProfile->ChannelInfo.ChannelList = NULL;
13297 pRoamProfile->ChannelInfo.numOfChannels = 0;
13298
Nitesh Shah044fd672016-10-13 18:53:25 +053013299 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013300 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13301 && !policy_mgr_is_hw_dbs_2x2_capable(
13302 pHddCtx->hdd_psoc)) {
13303 policy_mgr_get_channel_from_scan_result(
13304 pHddCtx->hdd_psoc,
13305 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013306 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013307 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013308 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13309 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013310 }
13311
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013312 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013313 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013314 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013315 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013316 goto ret_status;
13317
13318conn_failure:
13319 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013320 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013321
13322ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013323 EXIT();
13324 return status;
13325}
13326
13327/**
13328 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13329 * @pAdapter: Pointer to adapter
13330 * @auth_type: Auth type
13331 *
13332 * This function is used to set the authentication type (OPEN/SHARED).
13333 *
13334 * Return: 0 for success, non-zero for failure
13335 */
13336static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13337 enum nl80211_auth_type auth_type)
13338{
13339 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13340 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13341
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013342 /*set authentication type */
13343 switch (auth_type) {
13344 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013345 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13347 break;
13348
13349 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013350 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013351 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013352 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13353 break;
13354
13355 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013356 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013357 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13358 break;
13359#ifdef FEATURE_WLAN_ESE
13360 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013361 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013362 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13363 break;
13364#endif
13365
13366 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013367 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013368 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13369 return -EINVAL;
13370 }
13371
13372 pWextState->roamProfile.AuthType.authType[0] =
13373 pHddStaCtx->conn_info.authType;
13374 return 0;
13375}
13376
13377/**
13378 * wlan_hdd_set_akm_suite() - set key management type
13379 * @pAdapter: Pointer to adapter
13380 * @key_mgmt: Key management type
13381 *
13382 * This function is used to set the key mgmt type(PSK/8021x).
13383 *
13384 * Return: 0 for success, non-zero for failure
13385 */
13386static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13387{
13388 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13389
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013390#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013391#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013392#endif
13393#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013394#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013395#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013396 /*set key mgmt type */
13397 switch (key_mgmt) {
13398 case WLAN_AKM_SUITE_PSK:
13399 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013400 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013401 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013402 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13403 break;
13404
13405 case WLAN_AKM_SUITE_8021X_SHA256:
13406 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013407 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013408 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013409 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13410 break;
13411#ifdef FEATURE_WLAN_ESE
13412#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13413#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13414 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013415 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013416 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13417 break;
13418#endif
13419#ifndef WLAN_AKM_SUITE_OSEN
13420#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13421#endif
13422 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013423 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013424 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13425 break;
13426
13427 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013428 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013429 return -EINVAL;
13430
13431 }
13432 return 0;
13433}
13434
13435/**
13436 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13437 * @pAdapter: Pointer to adapter
13438 * @cipher: Cipher type
13439 * @ucast: Unicast flag
13440 *
13441 * This function is used to set the encryption type
13442 * (NONE/WEP40/WEP104/TKIP/CCMP).
13443 *
13444 * Return: 0 for success, non-zero for failure
13445 */
13446static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13447 u32 cipher, bool ucast)
13448{
13449 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13450 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13451 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013453 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013454 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13456 } else {
13457
13458 /*set encryption method */
13459 switch (cipher) {
13460 case IW_AUTH_CIPHER_NONE:
13461 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13462 break;
13463
13464 case WLAN_CIPHER_SUITE_WEP40:
13465 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13466 break;
13467
13468 case WLAN_CIPHER_SUITE_WEP104:
13469 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13470 break;
13471
13472 case WLAN_CIPHER_SUITE_TKIP:
13473 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13474 break;
13475
13476 case WLAN_CIPHER_SUITE_CCMP:
13477 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13478 break;
13479#ifdef FEATURE_WLAN_WAPI
13480 case WLAN_CIPHER_SUITE_SMS4:
13481 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13482 break;
13483#endif
13484
13485#ifdef FEATURE_WLAN_ESE
13486 case WLAN_CIPHER_SUITE_KRK:
13487 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13488 break;
13489#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13490 case WLAN_CIPHER_SUITE_BTK:
13491 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13492 break;
13493#endif
13494#endif
13495 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013496 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013497 return -EOPNOTSUPP;
13498 }
13499 }
13500
13501 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013502 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013503 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13504 pWextState->roamProfile.EncryptionType.numEntries = 1;
13505 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13506 encryptionType;
13507 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013508 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013509 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13510 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13511 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13512 encryptionType;
13513 }
13514
13515 return 0;
13516}
13517
13518/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013519 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13520 * @wext_state: Pointer to wext state
13521 * @gen_ie: Pointer to IE data
13522 * @len: length of IE data
13523 *
13524 * Return: 0 for success, non-zero for failure
13525 */
13526static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13527 const uint8_t *gen_ie, uint16_t len)
13528{
13529 uint16_t cur_add_ie_len =
13530 wext_state->assocAddIE.length;
13531
13532 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13533 (wext_state->assocAddIE.length + len)) {
13534 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13535 QDF_ASSERT(0);
13536 return -ENOMEM;
13537 }
13538 memcpy(wext_state->assocAddIE.addIEdata +
13539 cur_add_ie_len, gen_ie, len);
13540 wext_state->assocAddIE.length += len;
13541
13542 wext_state->roamProfile.pAddIEAssoc =
13543 wext_state->assocAddIE.addIEdata;
13544 wext_state->roamProfile.nAddIEAssocLength =
13545 wext_state->assocAddIE.length;
13546 return 0;
13547}
13548
13549/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013550 * wlan_hdd_cfg80211_set_ie() - set IEs
13551 * @pAdapter: Pointer to adapter
13552 * @ie: Pointer ot ie
13553 * @ie: IE length
13554 *
13555 * Return: 0 for success, non-zero for failure
13556 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013557static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013558 size_t ie_len)
13559{
13560 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13561 const uint8_t *genie = ie;
13562 uint16_t remLen = ie_len;
13563#ifdef FEATURE_WLAN_WAPI
13564 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13565 u16 *tmp;
13566 uint16_t akmsuiteCount;
13567 int *akmlist;
13568#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013569 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013570
13571 /* clear previous assocAddIE */
13572 pWextState->assocAddIE.length = 0;
13573 pWextState->roamProfile.bWPSAssociation = false;
13574 pWextState->roamProfile.bOSENAssociation = false;
13575
13576 while (remLen >= 2) {
13577 uint16_t eLen = 0;
13578 uint8_t elementId;
13579 elementId = *genie++;
13580 eLen = *genie++;
13581 remLen -= 2;
13582
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013583 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013584
13585 switch (elementId) {
13586 case DOT11F_EID_WPA:
13587 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 -070013588 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013589 return -EINVAL;
13590 } else if (0 ==
13591 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13592 uint16_t curAddIELen =
13593 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013594 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013595
13596 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13597 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013598 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013599 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013600 return -ENOMEM;
13601 }
13602 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13603 memcpy(pWextState->assocAddIE.addIEdata +
13604 curAddIELen, genie - 2, eLen + 2);
13605 pWextState->assocAddIE.length += eLen + 2;
13606
13607 pWextState->roamProfile.bWPSAssociation = true;
13608 pWextState->roamProfile.pAddIEAssoc =
13609 pWextState->assocAddIE.addIEdata;
13610 pWextState->roamProfile.nAddIEAssocLength =
13611 pWextState->assocAddIE.length;
13612 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013613 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013614 memset(pWextState->WPARSNIE, 0,
13615 MAX_WPA_RSN_IE_LEN);
13616 memcpy(pWextState->WPARSNIE, genie - 2,
13617 (eLen + 2));
13618 pWextState->roamProfile.pWPAReqIE =
13619 pWextState->WPARSNIE;
13620 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13621 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13622 P2P_OUI_TYPE_SIZE))) {
13623 uint16_t curAddIELen =
13624 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013625 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013626
13627 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13628 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013629 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013630 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013631 return -ENOMEM;
13632 }
13633 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13634 memcpy(pWextState->assocAddIE.addIEdata +
13635 curAddIELen, genie - 2, eLen + 2);
13636 pWextState->assocAddIE.length += eLen + 2;
13637
13638 pWextState->roamProfile.pAddIEAssoc =
13639 pWextState->assocAddIE.addIEdata;
13640 pWextState->roamProfile.nAddIEAssocLength =
13641 pWextState->assocAddIE.length;
13642 }
13643#ifdef WLAN_FEATURE_WFD
13644 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13645 WFD_OUI_TYPE_SIZE)) &&
13646 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013647 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013648 pAdapter->device_mode)) {
13649 uint16_t curAddIELen =
13650 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013651 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013652
13653 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13654 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013655 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013656 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013657 return -ENOMEM;
13658 }
13659 /* WFD IE is saved to Additional IE ; it should
13660 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013661 * WFD IE
13662 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013663 memcpy(pWextState->assocAddIE.addIEdata +
13664 curAddIELen, genie - 2, eLen + 2);
13665 pWextState->assocAddIE.length += eLen + 2;
13666
13667 pWextState->roamProfile.pAddIEAssoc =
13668 pWextState->assocAddIE.addIEdata;
13669 pWextState->roamProfile.nAddIEAssocLength =
13670 pWextState->assocAddIE.length;
13671 }
13672#endif
13673 /* Appending HS 2.0 Indication Element in Assiciation Request */
13674 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13675 HS20_OUI_TYPE_SIZE))) {
13676 uint16_t curAddIELen =
13677 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013678 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013679
13680 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13681 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013682 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013683 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013684 return -ENOMEM;
13685 }
13686 memcpy(pWextState->assocAddIE.addIEdata +
13687 curAddIELen, genie - 2, eLen + 2);
13688 pWextState->assocAddIE.length += eLen + 2;
13689
13690 pWextState->roamProfile.pAddIEAssoc =
13691 pWextState->assocAddIE.addIEdata;
13692 pWextState->roamProfile.nAddIEAssocLength =
13693 pWextState->assocAddIE.length;
13694 }
13695 /* Appending OSEN Information Element in Assiciation Request */
13696 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13697 OSEN_OUI_TYPE_SIZE))) {
13698 uint16_t curAddIELen =
13699 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013700 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013701
13702 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13703 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013704 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013705 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013706 return -ENOMEM;
13707 }
13708 memcpy(pWextState->assocAddIE.addIEdata +
13709 curAddIELen, genie - 2, eLen + 2);
13710 pWextState->assocAddIE.length += eLen + 2;
13711
13712 pWextState->roamProfile.bOSENAssociation = true;
13713 pWextState->roamProfile.pAddIEAssoc =
13714 pWextState->assocAddIE.addIEdata;
13715 pWextState->roamProfile.nAddIEAssocLength =
13716 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013717 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13718 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013719 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013720 status = wlan_hdd_add_assoc_ie(pWextState,
13721 genie - 2, eLen + 2);
13722 if (status)
13723 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013724 } else {
13725 uint16_t add_ie_len =
13726 pWextState->assocAddIE.length;
13727
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013728 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013729
13730 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13731 (pWextState->assocAddIE.length + eLen)) {
13732 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013733 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013734 return -ENOMEM;
13735 }
13736
13737 memcpy(pWextState->assocAddIE.addIEdata +
13738 add_ie_len, genie - 2, eLen + 2);
13739 pWextState->assocAddIE.length += eLen + 2;
13740
13741 pWextState->roamProfile.pAddIEAssoc =
13742 pWextState->assocAddIE.addIEdata;
13743 pWextState->roamProfile.nAddIEAssocLength =
13744 pWextState->assocAddIE.length;
13745 }
13746 break;
13747 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013748 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013749 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13750 memcpy(pWextState->WPARSNIE, genie - 2,
13751 (eLen + 2));
13752 pWextState->roamProfile.pRSNReqIE =
13753 pWextState->WPARSNIE;
13754 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13755 break;
13756 /*
13757 * Appending Extended Capabilities with Interworking bit set
13758 * in Assoc Req.
13759 *
13760 * In assoc req this EXT Cap will only be taken into account if
13761 * interworkingService bit is set to 1. Currently
13762 * driver is only interested in interworkingService capability
13763 * from supplicant. If in future any other EXT Cap info is
13764 * required from supplicat, it needs to be handled while
13765 * sending Assoc Req in LIM.
13766 */
13767 case DOT11F_EID_EXTCAP:
13768 {
13769 uint16_t curAddIELen =
13770 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013771 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013772
13773 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13774 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013775 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013776 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013777 return -ENOMEM;
13778 }
13779 memcpy(pWextState->assocAddIE.addIEdata +
13780 curAddIELen, genie - 2, eLen + 2);
13781 pWextState->assocAddIE.length += eLen + 2;
13782
13783 pWextState->roamProfile.pAddIEAssoc =
13784 pWextState->assocAddIE.addIEdata;
13785 pWextState->roamProfile.nAddIEAssocLength =
13786 pWextState->assocAddIE.length;
13787 break;
13788 }
13789#ifdef FEATURE_WLAN_WAPI
13790 case WLAN_EID_WAPI:
13791 /* Setting WAPI Mode to ON=1 */
13792 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013793 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013794 tmp = (u16 *) ie;
13795 tmp = tmp + 2; /* Skip element Id and Len, Version */
13796 akmsuiteCount = WPA_GET_LE16(tmp);
13797 tmp = tmp + 1;
13798 akmlist = (int *)(tmp);
13799 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13800 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13801 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013802 hdd_err("Invalid akmSuite count: %u",
13803 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013804 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013805 return -EINVAL;
13806 }
13807
13808 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013809 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013810 pAdapter->wapi_info.wapiAuthMode =
13811 WAPI_AUTH_MODE_PSK;
13812 }
13813 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013814 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013815 pAdapter->wapi_info.wapiAuthMode =
13816 WAPI_AUTH_MODE_CERT;
13817 }
13818 break;
13819#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013820 case DOT11F_EID_SUPPOPERATINGCLASSES:
13821 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013822 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013823 status = wlan_hdd_add_assoc_ie(pWextState,
13824 genie - 2, eLen + 2);
13825 if (status)
13826 return status;
13827 break;
13828 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013829 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013830 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013831 /* when Unknown IE is received we break
13832 * and continue to the next IE in the buffer
13833 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013834 break;
13835 }
13836 genie += eLen;
13837 remLen -= eLen;
13838 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013839 return 0;
13840}
13841
13842/**
13843 * hdd_is_wpaie_present() - check for WPA ie
13844 * @ie: Pointer to ie
13845 * @ie_len: Ie length
13846 *
13847 * Parse the received IE to find the WPA IE
13848 *
13849 * Return: true if wpa ie is found else false
13850 */
13851static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13852{
13853 uint8_t eLen = 0;
13854 uint16_t remLen = ie_len;
13855 uint8_t elementId = 0;
13856
13857 while (remLen >= 2) {
13858 elementId = *ie++;
13859 eLen = *ie++;
13860 remLen -= 2;
13861 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013862 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013863 return false;
13864 }
13865 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13866 /* OUI - 0x00 0X50 0XF2
13867 * WPA Information Element - 0x01
13868 * WPA version - 0x01
13869 */
13870 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13871 return true;
13872 }
13873 ie += eLen;
13874 remLen -= eLen;
13875 }
13876 return false;
13877}
13878
13879/**
13880 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13881 * @pAdapter: Pointer to adapter
13882 * @req: Pointer to security parameters
13883 *
13884 * Return: 0 for success, non-zero for failure
13885 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013886static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13887 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013888{
13889 int status = 0;
13890 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13891 ENTER();
13892
13893 /*set wpa version */
13894 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13895
13896 if (req->crypto.wpa_versions) {
13897 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13898 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13899 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13900 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13901 }
13902 }
13903
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013904 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013905
13906 /*set authentication type */
13907 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13908
13909 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013910 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013911 return status;
13912 }
13913
13914 /*set key mgmt type */
13915 if (req->crypto.n_akm_suites) {
13916 status =
13917 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13918 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013919 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013920 return status;
13921 }
13922 }
13923
13924 /*set pairwise cipher type */
13925 if (req->crypto.n_ciphers_pairwise) {
13926 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13927 req->crypto.
13928 ciphers_pairwise[0],
13929 true);
13930 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013931 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013932 return status;
13933 }
13934 } else {
13935 /*Reset previous cipher suite to none */
13936 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13937 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013938 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013939 return status;
13940 }
13941 }
13942
13943 /*set group cipher type */
13944 status =
13945 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13946 false);
13947
13948 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013949 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013950 return status;
13951 }
13952#ifdef WLAN_FEATURE_11W
13953 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13954#endif
13955
13956 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13957 if (req->ie_len) {
13958 status =
13959 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13960 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013961 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013962 return status;
13963 }
13964 }
13965
13966 /*incase of WEP set default key information */
13967 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013968 u8 key_len = req->key_len;
13969 u8 key_idx = req->key_idx;
13970
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013971 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13972 || (WLAN_CIPHER_SUITE_WEP104 ==
13973 req->crypto.ciphers_pairwise[0])
13974 ) {
13975 if (IW_AUTH_KEY_MGMT_802_1X
13976 ==
13977 (pWextState->
13978 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013979 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013980 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013981 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013982
Jeff Johnson68755312017-02-10 11:46:55 -080013983 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13984 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013985 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080013986 key_idx, key_len);
13987 qdf_mem_copy(&pWextState->roamProfile.
13988 Keys.
13989 KeyMaterial[key_idx][0],
13990 req->key, key_len);
13991 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013992 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013993 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013994 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013995 }
13996 }
13997 }
13998
13999 return status;
14000}
14001
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014002int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014003{
14004 unsigned long rc;
14005 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014006 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014007 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014008
14009 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014010 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14011 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014012 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014013 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14014 }
14015 /*
14016 * If firmware has already started roaming process, driver
14017 * needs to defer the processing of this disconnect request.
14018 *
14019 */
14020 if (hdd_is_roaming_in_progress(pAdapter)) {
14021 /*
14022 * Defer the disconnect action until firmware roaming
14023 * result is received. If STA is in connected state after
14024 * that, send the disconnect command to CSR, otherwise
14025 * CSR would have already sent disconnect event to upper
14026 * layer.
14027 */
14028
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014029 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014030 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14031 pAdapter->cfg80211_disconnect_reason =
14032 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14033 return 0;
14034 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014035
Jeff Johnson9edf9572016-10-03 15:24:49 -070014036 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014037 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14038 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14039 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014040 hdd_conn_set_connection_state(pAdapter,
14041 eConnectionState_Disconnecting);
14042 /* Issue disconnect to CSR */
14043 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014044
14045 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14046 pAdapter->sessionId,
14047 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14048 /*
14049 * Wait here instead of returning directly, this will block the
14050 * next connect command and allow processing of the scan for
14051 * ssid and the previous connect command in CSR. Else we might
14052 * hit some race conditions leading to SME and HDD out of sync.
14053 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014054 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014055 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014056 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014057 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014058 (int)status);
14059 pHddStaCtx->staDebugState = status;
14060 result = -EINVAL;
14061 goto disconnected;
14062 }
14063
14064 rc = wait_for_completion_timeout(
14065 &pAdapter->disconnect_comp_var,
14066 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014067 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014068 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014069 pAdapter->sessionId, pHddStaCtx->staDebugState);
14070 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014071 }
14072 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014073 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014074 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014075 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014076 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014077 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014078 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014079 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014080 }
14081 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014082disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014083 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14084 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014085}
14086
14087/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014088 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14089 * @adapter: Pointer to the HDD adapter
14090 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014091 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014092 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014093 * This function will start reassociation if prev_bssid is set and bssid/
14094 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014095 *
Naveen Rawat07332902016-07-27 09:13:17 -070014096 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014097 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014098#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14099 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014100static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14101 struct cfg80211_connect_params *req,
14102 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014103{
Naveen Rawat07332902016-07-27 09:13:17 -070014104 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014105 const uint8_t *bssid = NULL;
14106 uint16_t channel = 0;
14107
14108 if (req->bssid)
14109 bssid = req->bssid;
14110 else if (req->bssid_hint)
14111 bssid = req->bssid_hint;
14112
14113 if (req->channel)
14114 channel = req->channel->hw_value;
14115 else if (req->channel_hint)
14116 channel = req->channel_hint->hw_value;
14117
14118 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014119 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014120 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014121 channel, MAC_ADDR_ARRAY(bssid));
14122 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014123 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014124 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014125 }
Naveen Rawat07332902016-07-27 09:13:17 -070014126 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014127}
14128#else
Naveen Rawat07332902016-07-27 09:13:17 -070014129static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14130 struct cfg80211_connect_params *req,
14131 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014132{
Naveen Rawat07332902016-07-27 09:13:17 -070014133 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014134}
14135#endif
14136
14137/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014138 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14139 * @wiphy: Pointer to wiphy
14140 * @dev: Pointer to network device
14141 * @req: Pointer to cfg80211 connect request
14142 *
14143 * This function is used to start the association process
14144 *
14145 * Return: 0 for success, non-zero for failure
14146 */
14147static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14148 struct net_device *ndev,
14149 struct cfg80211_connect_params *req)
14150{
14151 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014152 u16 channel;
14153#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14154 const u8 *bssid_hint = req->bssid_hint;
14155#else
14156 const u8 *bssid_hint = NULL;
14157#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014158 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14159 hdd_context_t *pHddCtx;
14160
14161 ENTER();
14162
Anurag Chouhan6d760662016-02-20 16:05:43 +053014163 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014164 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014165 return -EINVAL;
14166 }
14167
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014168 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14169 hdd_err("invalid session id: %d", pAdapter->sessionId);
14170 return -EINVAL;
14171 }
14172
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014173 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014174 TRACE_CODE_HDD_CFG80211_CONNECT,
14175 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014176 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014177 hdd_device_mode_to_string(pAdapter->device_mode),
14178 pAdapter->device_mode);
14179
Krunal Sonib4326f22016-03-10 13:05:51 -080014180 if (pAdapter->device_mode != QDF_STA_MODE &&
14181 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014182 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014183 hdd_device_mode_to_string(pAdapter->device_mode),
14184 pAdapter->device_mode);
14185 return -EINVAL;
14186 }
14187
14188 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14189 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014190 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014191 return -EINVAL;
14192 }
14193
14194 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014195 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014196 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014197
Naveen Rawat07332902016-07-27 09:13:17 -070014198 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014199 return status;
14200
Agrawal Ashishf156e942016-08-04 14:54:47 +053014201 /* Try disconnecting if already in connected state */
14202 status = wlan_hdd_try_disconnect(pAdapter);
14203 if (0 > status) {
14204 hdd_err("Failed to disconnect the existing connection");
14205 return -EALREADY;
14206 }
14207
14208 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014209 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014210 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14211 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014212 pAdapter->device_mode),
14213 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014214 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014215 return -ECONNREFUSED;
14216 }
14217 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014218 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14219 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014220 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014221 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014222 return -ECONNREFUSED;
14223 }
14224 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014225
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014226 /*initialise security parameters */
14227 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14228
14229 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014230 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014231 return status;
14232 }
14233
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014234 if (req->channel)
14235 channel = req->channel->hw_value;
14236 else
14237 channel = 0;
14238 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14239 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014240 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014241 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014242 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014243 return status;
14244 }
14245 EXIT();
14246 return status;
14247}
14248
14249/**
14250 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14251 * @wiphy: Pointer to wiphy
14252 * @dev: Pointer to network device
14253 * @req: Pointer to cfg80211 connect request
14254 *
14255 * Return: 0 for success, non-zero for failure
14256 */
14257static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14258 struct net_device *ndev,
14259 struct cfg80211_connect_params *req)
14260{
14261 int ret;
14262 cds_ssr_protect(__func__);
14263 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14264 cds_ssr_unprotect(__func__);
14265
14266 return ret;
14267}
14268
14269/**
14270 * wlan_hdd_disconnect() - hdd disconnect api
14271 * @pAdapter: Pointer to adapter
14272 * @reason: Disconnect reason code
14273 *
14274 * This function is used to issue a disconnect request to SME
14275 *
14276 * Return: 0 for success, non-zero for failure
14277 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014278static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014279{
14280 int status, result = 0;
14281 unsigned long rc;
14282 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14283 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014284 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014285 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014286
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014287 ENTER();
14288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014289 status = wlan_hdd_validate_context(pHddCtx);
14290
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014291 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014292 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014293 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014294 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014295 status = sme_stop_roaming(hal, pAdapter->sessionId,
14296 eCsrHddIssued);
14297 }
14298 /*
14299 * If firmware has already started roaming process, driver
14300 * needs to defer the processing of this disconnect request.
14301 */
14302 if (hdd_is_roaming_in_progress(pAdapter)) {
14303 /*
14304 * Defer the disconnect action until firmware roaming
14305 * result is received. If STA is in connected state after
14306 * that, send the disconnect command to CSR, otherwise
14307 * CSR would have already sent disconnect event to upper
14308 * layer.
14309 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014310 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014311 pAdapter->defer_disconnect =
14312 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14313 pAdapter->cfg80211_disconnect_reason = reason;
14314 return 0;
14315 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014316
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014317 prev_conn_state = pHddStaCtx->conn_info.connState;
14318
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014319 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014320 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014321 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014322 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014323 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014324 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14325 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14326
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014327 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014328
14329 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14330 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014331 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14332 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014333 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014334 result = 0;
14335 goto disconnected;
14336 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14337 /*
14338 * Wait here instead of returning directly, this will block the
14339 * next connect command and allow processing of the scan for
14340 * ssid and the previous connect command in CSR. Else we might
14341 * hit some race conditions leading to SME and HDD out of sync.
14342 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014343 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014345 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014346 pHddStaCtx->staDebugState = status;
14347 result = -EINVAL;
14348 goto disconnected;
14349 }
14350 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14351 msecs_to_jiffies
14352 (WLAN_WAIT_TIME_DISCONNECT));
14353
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014354 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014355 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014356 result = -ETIMEDOUT;
14357 }
14358disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014359 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14360#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14361 /* Sending disconnect event to userspace for kernel version < 3.11
14362 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14363 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014364 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014365 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14366 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367#endif
14368
14369 return result;
14370}
14371
14372/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014373 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14374 * @reason: ieee80211 reason code.
14375 *
14376 * This utility function helps log string conversion of reason code.
14377 *
14378 * Return: string conversion of reason code, if match found;
14379 * "Unknown" otherwise.
14380 */
14381static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14382{
14383 switch (reason) {
14384 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14385 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14386 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14387 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14388 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14389 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14390 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14391 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14392 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14393 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14394 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14395 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14396 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14397 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14398 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14399 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14400 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14401 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14402 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14403 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14404 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14405 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14406 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14407 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14408 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14409 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14410 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14411 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14412 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14413 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14414 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14415 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14416 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14417 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14418 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14419 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14420 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14421 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14422 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14423 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14424 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14425 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14426 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14427 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14428 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14429 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14430 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14431 default:
14432 return "Unknown";
14433 }
14434}
14435
14436/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014437 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14438 * @wiphy: Pointer to wiphy
14439 * @dev: Pointer to network device
14440 * @reason: Disconnect reason code
14441 *
14442 * This function is used to issue a disconnect request to SME
14443 *
14444 * Return: 0 for success, non-zero for failure
14445 */
14446static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14447 struct net_device *dev, u16 reason)
14448{
14449 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14450 int status;
14451 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14452 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14453#ifdef FEATURE_WLAN_TDLS
14454 uint8_t staIdx;
14455#endif
14456
14457 ENTER();
14458
Anurag Chouhan6d760662016-02-20 16:05:43 +053014459 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014460 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014461 return -EINVAL;
14462 }
14463
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014464 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014465 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014466 return -EINVAL;
14467 }
14468
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014469 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014470 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14471 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014472 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014473 hdd_device_mode_to_string(pAdapter->device_mode),
14474 pAdapter->device_mode, reason);
14475
14476 status = wlan_hdd_validate_context(pHddCtx);
14477
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014478 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014479 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014480
14481 /* Issue disconnect request to SME, if station is in connected state */
14482 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14483 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14484 eCsrRoamDisconnectReason reasonCode =
14485 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14486 hdd_scaninfo_t *pScanInfo;
14487
14488 switch (reason) {
14489 case WLAN_REASON_MIC_FAILURE:
14490 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14491 break;
14492
14493 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14494 case WLAN_REASON_DISASSOC_AP_BUSY:
14495 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14496 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14497 break;
14498
14499 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14500 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14501 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14502 break;
14503
14504 case WLAN_REASON_DEAUTH_LEAVING:
14505 reasonCode =
14506 pHddCtx->config->
14507 gEnableDeauthToDisassocMap ?
14508 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14509 eCSR_DISCONNECT_REASON_DEAUTH;
14510 break;
14511 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14512 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14513 break;
14514 default:
14515 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14516 break;
14517 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014518 pScanInfo = &pAdapter->scan_info;
14519 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014520 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014521 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014522 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523 eCSR_SCAN_ABORT_DEFAULT);
14524 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014525 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014526#ifdef FEATURE_WLAN_TDLS
14527 /* First clean up the tdls peers if any */
14528 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14529 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14530 pAdapter->sessionId)
14531 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14532 uint8_t *mac;
14533 mac =
14534 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014535 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014536 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014537 pHddCtx->tdlsConnInfo[staIdx].staId,
14538 pAdapter->sessionId,
14539 MAC_ADDR_ARRAY(mac));
14540 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14541 (pAdapter),
14542 pAdapter->sessionId, mac);
14543 }
14544 }
14545#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014546 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14547 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014548 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14549 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014550 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014551 return -EINVAL;
14552 }
14553 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014554 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014555 pHddStaCtx->conn_info.connState);
14556 }
14557
14558 return status;
14559}
14560
14561/**
14562 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14563 * @wiphy: Pointer to wiphy
14564 * @dev: Pointer to network device
14565 * @reason: Disconnect reason code
14566 *
14567 * Return: 0 for success, non-zero for failure
14568 */
14569static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14570 struct net_device *dev, u16 reason)
14571{
14572 int ret;
14573 cds_ssr_protect(__func__);
14574 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14575 cds_ssr_unprotect(__func__);
14576
14577 return ret;
14578}
14579
14580/**
14581 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14582 * @pAdapter: Pointer to adapter
14583 * @param: Pointer to IBSS parameters
14584 *
14585 * This function is used to initialize the security settings in IBSS mode
14586 *
14587 * Return: 0 for success, non-zero for failure
14588 */
14589static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14590 struct cfg80211_ibss_params
14591 *params)
14592{
14593 int status = 0;
14594 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14595 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14596 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14597
14598 ENTER();
14599
14600 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014601 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014602 pHddStaCtx->ibss_enc_key_installed = 0;
14603
14604 if (params->ie_len && (NULL != params->ie)) {
14605 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14606 params->ie_len, WLAN_EID_RSN)) {
14607 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14608 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14609 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14610 tDot11fIEWPA dot11WPAIE;
14611 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14612 u8 *ie;
14613
14614 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14615 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14616 params->ie_len,
14617 DOT11F_EID_WPA);
14618 if (NULL != ie) {
14619 pWextState->wpaVersion =
14620 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014621 /* Unpack the WPA IE
14622 * Skip past the EID byte and length byte
14623 * and four byte WiFi OUI
14624 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014625 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014626 &ie[2 + 4], ie[1] - 4,
14627 &dot11WPAIE, false);
14628 /*
14629 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014630 * encType for unicast cipher for
14631 * wpa-none is none
14632 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014633 encryptionType =
14634 hdd_translate_wpa_to_csr_encryption_type
14635 (dot11WPAIE.multicast_cipher);
14636 }
14637 }
14638
14639 status =
14640 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14641 params->ie_len);
14642
14643 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014644 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014645 return status;
14646 }
14647 }
14648
14649 pWextState->roamProfile.AuthType.authType[0] =
14650 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14651
14652 if (params->privacy) {
14653 /* Security enabled IBSS, At this time there is no information
14654 * available about the security paramters, so initialise the
14655 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14656 * The correct security parameters will be updated later in
14657 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14658 * set inorder enable privacy bit in beacons
14659 */
14660
14661 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14662 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014663 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014664 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14665 pWextState->roamProfile.EncryptionType.numEntries = 1;
14666 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14667 encryptionType;
14668 return status;
14669}
14670
14671/**
14672 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14673 * @wiphy: Pointer to wiphy
14674 * @dev: Pointer to network device
14675 * @param: Pointer to IBSS join parameters
14676 *
14677 * This function is used to create/join an IBSS network
14678 *
14679 * Return: 0 for success, non-zero for failure
14680 */
14681static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14682 struct net_device *dev,
14683 struct cfg80211_ibss_params *params)
14684{
14685 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14686 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14687 tCsrRoamProfile *pRoamProfile;
14688 int status;
14689 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14690 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014691 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014692 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693
14694 ENTER();
14695
Anurag Chouhan6d760662016-02-20 16:05:43 +053014696 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014697 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014698 return -EINVAL;
14699 }
14700
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014701 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014702 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014703 return -EINVAL;
14704 }
14705
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014706 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014707 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14708 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014709 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014710 hdd_device_mode_to_string(pAdapter->device_mode),
14711 pAdapter->device_mode);
14712
14713 status = wlan_hdd_validate_context(pHddCtx);
14714
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014715 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014716 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014717
14718 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014719 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014720 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14721 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14722 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14723 int indx;
14724
14725 /* Get channel number */
14726 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014727 params->
14728 chandef.
14729 chan->
14730 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014731
14732 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14733 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014734 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014735 return -EOPNOTSUPP;
14736 }
14737
14738 for (indx = 0; indx < numChans; indx++) {
14739 if (channelNum == validChan[indx]) {
14740 break;
14741 }
14742 }
14743 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014744 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014745 return -EINVAL;
14746 }
14747 }
14748
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014749 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14750 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014751 hdd_err("This concurrency combination is not allowed");
14752 return -ECONNREFUSED;
14753 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014754
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014755 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014756 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014757 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014758
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014759 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14760 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014761 SIR_UPDATE_REASON_JOIN_IBSS);
14762 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014763 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014764 return -EINVAL;
14765 }
14766
14767 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014768 status = policy_mgr_wait_for_connection_update(
14769 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014770 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014771 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014772 return -EINVAL;
14773 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014774 }
14775
14776 /*Try disconnecting if already in connected state */
14777 status = wlan_hdd_try_disconnect(pAdapter);
14778 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014779 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014780 return -EALREADY;
14781 }
14782
14783 pRoamProfile = &pWextState->roamProfile;
14784
14785 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014786 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014787 return -EINVAL;
14788 }
14789
14790 /* enable selected protection checks in IBSS mode */
14791 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14792
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014793 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014794 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14795 pHddCtx->config->
14796 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014797 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014798 }
14799
14800 /* BSSID is provided by upper layers hence no need to AUTO generate */
14801 if (NULL != params->bssid) {
14802 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014803 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014804 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014805 return -EIO;
14806 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014807 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014808 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14809 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014810 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014811 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014812 return -EIO;
14813 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014814 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014815 }
14816 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14817 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14818 pRoamProfile->beaconInterval = params->beacon_interval;
14819 else {
14820 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014821 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014822 params->beacon_interval, pRoamProfile->beaconInterval);
14823 }
14824
14825 /* Set Channel */
14826 if (channelNum) {
14827 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014828 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014829 pRoamProfile->ChannelInfo.numOfChannels = 1;
14830 pHddStaCtx->conn_info.operationChannel = channelNum;
14831 pRoamProfile->ChannelInfo.ChannelList =
14832 &pHddStaCtx->conn_info.operationChannel;
14833 }
14834
14835 /* Initialize security parameters */
14836 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14837 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014838 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014839 return status;
14840 }
14841
14842 /* Issue connect start */
14843 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14844 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014845 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014846 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014847 operationChannel,
14848 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014849
14850 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014851 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014852 return status;
14853 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014854 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014855 return 0;
14856}
14857
14858/**
14859 * wlan_hdd_cfg80211_join_ibss() - join ibss
14860 * @wiphy: Pointer to wiphy
14861 * @dev: Pointer to network device
14862 * @param: Pointer to IBSS join parameters
14863 *
14864 * This function is used to create/join an IBSS network
14865 *
14866 * Return: 0 for success, non-zero for failure
14867 */
14868static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14869 struct net_device *dev,
14870 struct cfg80211_ibss_params *params)
14871{
14872 int ret = 0;
14873
14874 cds_ssr_protect(__func__);
14875 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14876 cds_ssr_unprotect(__func__);
14877
14878 return ret;
14879}
14880
14881/**
14882 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14883 * @wiphy: Pointer to wiphy
14884 * @dev: Pointer to network device
14885 *
14886 * This function is used to leave an IBSS network
14887 *
14888 * Return: 0 for success, non-zero for failure
14889 */
14890static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14891 struct net_device *dev)
14892{
14893 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14894 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14895 tCsrRoamProfile *pRoamProfile;
14896 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14897 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014898 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014899 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014900 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014901
14902 ENTER();
14903
Anurag Chouhan6d760662016-02-20 16:05:43 +053014904 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014905 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014906 return -EINVAL;
14907 }
14908
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014909 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014910 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014911 return -EINVAL;
14912 }
14913
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014914 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014915 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14916 pAdapter->sessionId,
14917 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14918 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014919 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014920 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014921
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014922 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014923 hdd_device_mode_to_string(pAdapter->device_mode),
14924 pAdapter->device_mode);
14925 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014926 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014927 return -EIO;
14928 }
14929
14930 pRoamProfile = &pWextState->roamProfile;
14931
14932 /* Issue disconnect only if interface type is set to IBSS */
14933 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014934 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014935 return -EINVAL;
14936 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014937 /* Clearing add IE of beacon */
14938 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14939 sizeof(tSirMacAddr));
14940 updateIE.smeSessionId = pAdapter->sessionId;
14941 updateIE.ieBufferlength = 0;
14942 updateIE.pAdditionIEBuffer = NULL;
14943 updateIE.append = true;
14944 updateIE.notify = true;
14945 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14946 &updateIE,
14947 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014948 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014949 }
14950
14951 /* Reset WNI_CFG_PROBE_RSP Flags */
14952 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014953
14954 /* Issue Disconnect request */
14955 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14956 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14957 pAdapter->sessionId,
14958 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014959 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014960 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014961 hal_status);
14962 return -EAGAIN;
14963 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014964
14965 /* wait for mc thread to cleanup and then return to upper stack
14966 * so by the time upper layer calls the change interface, we are
14967 * all set to proceed further
14968 */
14969 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14970 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14971 if (!rc) {
14972 hdd_err("Failed to disconnect, timed out");
14973 return -ETIMEDOUT;
14974 }
14975
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014976 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014977 return 0;
14978}
14979
14980/**
14981 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14982 * @wiphy: Pointer to wiphy
14983 * @dev: Pointer to network device
14984 *
14985 * This function is used to leave an IBSS network
14986 *
14987 * Return: 0 for success, non-zero for failure
14988 */
14989static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14990 struct net_device *dev)
14991{
14992 int ret = 0;
14993
14994 cds_ssr_protect(__func__);
14995 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14996 cds_ssr_unprotect(__func__);
14997
14998 return ret;
14999}
15000
15001/**
15002 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15003 * @wiphy: Pointer to wiphy
15004 * @changed: Parameters changed
15005 *
15006 * This function is used to set the phy parameters. RTS Threshold/FRAG
15007 * Threshold/Retry Count etc.
15008 *
15009 * Return: 0 for success, non-zero for failure
15010 */
15011static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15012 u32 changed)
15013{
15014 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15015 tHalHandle hHal = pHddCtx->hHal;
15016 int status;
15017
15018 ENTER();
15019
Anurag Chouhan6d760662016-02-20 16:05:43 +053015020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015021 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015022 return -EINVAL;
15023 }
15024
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015025 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015026 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15027 NO_SESSION, wiphy->rts_threshold));
15028 status = wlan_hdd_validate_context(pHddCtx);
15029
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015030 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015031 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015032
15033 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15034 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15035 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15036
15037 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15038 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015039 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015040 rts_threshold);
15041 return -EINVAL;
15042 }
15043
15044 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15045 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015046 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015047 rts_threshold);
15048 return -EIO;
15049 }
15050
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015051 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015052 }
15053
15054 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15055 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15056 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15057 wiphy->frag_threshold;
15058
15059 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15060 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015061 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015062 frag_threshold);
15063 return -EINVAL;
15064 }
15065
15066 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15067 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015068 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015069 frag_threshold);
15070 return -EIO;
15071 }
15072
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015073 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015074 }
15075
15076 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15077 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15078 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15079 wiphy->retry_short : wiphy->retry_long;
15080
15081 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15082 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015083 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015084 return -EINVAL;
15085 }
15086
15087 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15088 if (0 != sme_cfg_set_int(hHal,
15089 WNI_CFG_LONG_RETRY_LIMIT,
15090 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015091 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015092 retry_value);
15093 return -EIO;
15094 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015095 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015096 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15097 if (0 != sme_cfg_set_int(hHal,
15098 WNI_CFG_SHORT_RETRY_LIMIT,
15099 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015100 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015101 retry_value);
15102 return -EIO;
15103 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015104 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015105 }
15106 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015107 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015108 return 0;
15109}
15110
15111/**
15112 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15113 * @wiphy: Pointer to wiphy
15114 * @changed: Parameters changed
15115 *
15116 * Return: 0 for success, non-zero for failure
15117 */
15118static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15119{
15120 int ret;
15121
15122 cds_ssr_protect(__func__);
15123 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15124 cds_ssr_unprotect(__func__);
15125
15126 return ret;
15127}
15128
15129/**
15130 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15131 * key
15132 * @wiphy: Pointer to wiphy
15133 * @dev: Pointer to network device
15134 * @key_index: Key index
15135 *
15136 * Return: 0
15137 */
15138static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15139 struct net_device *netdev,
15140 u8 key_index)
15141{
15142 ENTER();
15143 return 0;
15144}
15145
15146/**
15147 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15148 * wlan_hdd_set_default_mgmt_key
15149 * @wiphy: pointer to wiphy
15150 * @netdev: pointer to net_device structure
15151 * @key_index: key index
15152 *
15153 * Return: 0 on success, error number on failure
15154 */
15155static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15156 struct net_device *netdev,
15157 u8 key_index)
15158{
15159 int ret;
15160
15161 cds_ssr_protect(__func__);
15162 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15163 cds_ssr_unprotect(__func__);
15164
15165 return ret;
15166}
15167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015168/**
15169 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15170 * @wiphy: Pointer to wiphy
15171 * @dev: Pointer to network device
15172 * @params: Pointer to tx queue parameters
15173 *
15174 * Return: 0
15175 */
15176static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15177 struct net_device *dev,
15178 struct ieee80211_txq_params *params)
15179{
15180 ENTER();
15181 return 0;
15182}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015183
15184/**
15185 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15186 * @wiphy: pointer to wiphy
15187 * @netdev: pointer to net_device structure
15188 * @params: pointer to ieee80211_txq_params
15189 *
15190 * Return: 0 on success, error number on failure
15191 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015192static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15193 struct net_device *dev,
15194 struct ieee80211_txq_params *params)
15195{
15196 int ret;
15197
15198 cds_ssr_protect(__func__);
15199 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15200 cds_ssr_unprotect(__func__);
15201
15202 return ret;
15203}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015204
15205/**
15206 * __wlan_hdd_cfg80211_del_station() - delete station v2
15207 * @wiphy: Pointer to wiphy
15208 * @param: Pointer to delete station parameter
15209 *
15210 * Return: 0 for success, non-zero for failure
15211 */
15212static
15213int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15214 struct net_device *dev,
15215 struct tagCsrDelStaParams *pDelStaParams)
15216{
15217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15218 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015219 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015220 hdd_hostapd_state_t *hapd_state;
15221 int status;
15222 uint8_t staId;
15223 uint8_t *mac;
15224
15225 ENTER();
15226
Anurag Chouhan6d760662016-02-20 16:05:43 +053015227 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015228 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015229 return -EINVAL;
15230 }
15231
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015232 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015233 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015234 return -EINVAL;
15235 }
15236
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015237 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015238 TRACE_CODE_HDD_CFG80211_DEL_STA,
15239 pAdapter->sessionId, pAdapter->device_mode));
15240
15241 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15242 status = wlan_hdd_validate_context(pHddCtx);
15243
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015244 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015245 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246
15247 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15248
Krunal Sonib4326f22016-03-10 13:05:51 -080015249 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15250 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015251
15252 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15253 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015254 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015255 return 0;
15256 }
15257
Anurag Chouhanc5548422016-02-24 18:33:27 +053015258 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015259 uint16_t i;
15260 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15261 if ((pAdapter->aStaInfo[i].isUsed) &&
15262 (!pAdapter->aStaInfo[i].
15263 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015264 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015265 mac,
15266 pAdapter->aStaInfo[i].
15267 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015268 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015269 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15270 hdd_ipa_wlan_evt(pAdapter,
15271 pAdapter->
15272 aStaInfo[i].
15273 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015274 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015275 mac);
15276 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015277 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015278 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015279 MAC_ADDR_ARRAY(mac));
15280
15281 if (pHddCtx->dev_dfs_cac_status ==
15282 DFS_CAC_IN_PROGRESS)
15283 goto fn_end;
15284
Wei Song2f76f642016-11-18 16:32:53 +080015285 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015286 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015287 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015288 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015289 hdd_softap_sta_deauth(pAdapter,
15290 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015291 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015292 pAdapter->aStaInfo[i].
15293 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015294 qdf_status =
15295 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015296 &hapd_state->
15297 qdf_sta_disassoc_event,
15298 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015299 if (!QDF_IS_STATUS_SUCCESS(
15300 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015301 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015302 }
15303 }
15304 }
15305 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015306 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015307 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015308 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015309 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015310 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015311 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015312 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015313 MAC_ADDR_ARRAY(mac));
15314 return -ENOENT;
15315 }
15316
15317 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15318 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015319 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015320 }
15321
15322 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15323 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015324 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015325 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015326 MAC_ADDR_ARRAY(mac));
15327 return -ENOENT;
15328 }
15329
15330 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15331
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015332 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015333 MAC_ADDR_ARRAY(mac));
15334
15335 /* Case: SAP in ACS selected DFS ch and client connected
15336 * Now Radar detected. Then if random channel is another
15337 * DFS ch then new CAC is initiated and no TX allowed.
15338 * So do not send any mgmt frames as it will timeout
15339 * during CAC.
15340 */
15341
15342 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15343 goto fn_end;
15344
Wei Song2f76f642016-11-18 16:32:53 +080015345 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015346 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15347 (pAdapter), pAdapter->sessionId,
15348 (uint8_t *)&pDelStaParams->peerMacAddr,
15349 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015350 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015351 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015352 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015353 pAdapter->aStaInfo[staId].isDeauthInProgress =
15354 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015355 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015356 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015357 MAC_ADDR_ARRAY(mac));
15358 return -ENOENT;
15359 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015360 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015361 &hapd_state->
15362 qdf_sta_disassoc_event,
15363 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015364 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015365 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015366 }
15367 }
15368 }
15369
15370fn_end:
15371 EXIT();
15372 return 0;
15373}
15374
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015375#if defined(USE_CFG80211_DEL_STA_V2)
15376/**
15377 * wlan_hdd_del_station() - delete station wrapper
15378 * @adapter: pointer to the hdd adapter
15379 *
15380 * Return: None
15381 */
15382void wlan_hdd_del_station(hdd_adapter_t *adapter)
15383{
15384 struct station_del_parameters del_sta;
15385 del_sta.mac = NULL;
15386 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15387 del_sta.reason_code = eCsrForcedDeauthSta;
15388
15389 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15390 &del_sta);
15391}
15392#else
15393void wlan_hdd_del_station(hdd_adapter_t *adapter)
15394{
15395 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15396}
15397#endif
15398
15399#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015400/**
15401 * wlan_hdd_cfg80211_del_station() - delete station v2
15402 * @wiphy: Pointer to wiphy
15403 * @param: Pointer to delete station parameter
15404 *
15405 * Return: 0 for success, non-zero for failure
15406 */
15407int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15408 struct net_device *dev,
15409 struct station_del_parameters *param)
15410#else
15411/**
15412 * wlan_hdd_cfg80211_del_station() - delete station
15413 * @wiphy: Pointer to wiphy
15414 * @mac: Pointer to station mac address
15415 *
15416 * Return: 0 for success, non-zero for failure
15417 */
15418#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15419int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15420 struct net_device *dev,
15421 const uint8_t *mac)
15422#else
15423int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15424 struct net_device *dev,
15425 uint8_t *mac)
15426#endif
15427#endif
15428{
15429 int ret;
15430 struct tagCsrDelStaParams delStaParams;
15431
15432 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015433#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015434 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015435 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015436 return -EINVAL;
15437 }
15438 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15439 param->subtype, &delStaParams);
15440#else
15441 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15442 (SIR_MAC_MGMT_DEAUTH >> 4),
15443 &delStaParams);
15444#endif
15445 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15446 cds_ssr_unprotect(__func__);
15447
15448 return ret;
15449}
15450
15451/**
15452 * __wlan_hdd_cfg80211_add_station() - add station
15453 * @wiphy: Pointer to wiphy
15454 * @mac: Pointer to station mac address
15455 * @pmksa: Pointer to add station parameter
15456 *
15457 * Return: 0 for success, non-zero for failure
15458 */
15459static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15460 struct net_device *dev,
15461 const uint8_t *mac,
15462 struct station_parameters *params)
15463{
15464 int status = -EPERM;
15465#ifdef FEATURE_WLAN_TDLS
15466 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15467 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15468 u32 mask, set;
15469
15470 ENTER();
15471
Anurag Chouhan6d760662016-02-20 16:05:43 +053015472 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015473 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015474 return -EINVAL;
15475 }
15476
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015477 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015478 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015479 return -EINVAL;
15480 }
15481
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015482 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015483 TRACE_CODE_HDD_CFG80211_ADD_STA,
15484 pAdapter->sessionId, params->listen_interval));
15485
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015486 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015487 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015488
15489 mask = params->sta_flags_mask;
15490
15491 set = params->sta_flags_set;
15492
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015493 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015494 MAC_ADDR_ARRAY(mac));
15495
15496 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15497 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015498#if defined(CONVERGED_TDLS_ENABLE)
15499 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15500 dev, mac);
15501#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015502 status =
15503 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015504#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015505 }
15506 }
15507#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015508 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015509 return status;
15510}
15511
15512/**
15513 * wlan_hdd_cfg80211_add_station() - add station
15514 * @wiphy: Pointer to wiphy
15515 * @mac: Pointer to station mac address
15516 * @pmksa: Pointer to add station parameter
15517 *
15518 * Return: 0 for success, non-zero for failure
15519 */
15520#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15521static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15522 struct net_device *dev,
15523 const uint8_t *mac,
15524 struct station_parameters *params)
15525#else
15526static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15527 struct net_device *dev, uint8_t *mac,
15528 struct station_parameters *params)
15529#endif
15530{
15531 int ret;
15532
15533 cds_ssr_protect(__func__);
15534 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15535 cds_ssr_unprotect(__func__);
15536
15537 return ret;
15538}
15539
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015540/**
15541 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15542 * @wiphy: Pointer to wiphy
15543 * @dev: Pointer to network device
15544 * @pmksa: Pointer to set pmksa parameter
15545 *
15546 * Return: 0 for success, non-zero for failure
15547 */
15548static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15549 struct net_device *dev,
15550 struct cfg80211_pmksa *pmksa)
15551{
15552 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15553 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15554 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015555 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015556 int status;
15557 tPmkidCacheInfo pmk_id;
15558
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015559 ENTER();
15560
Anurag Chouhan6d760662016-02-20 16:05:43 +053015561 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015562 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015563 return -EINVAL;
15564 }
15565
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015566 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015567 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015568 return -EINVAL;
15569 }
15570
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015571 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015572 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015573 return -EINVAL;
15574 }
15575
15576 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015577 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015578 pmksa->bssid, pmksa->pmkid);
15579 return -EINVAL;
15580 }
15581
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015582 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015583 MAC_ADDR_ARRAY(pmksa->bssid));
15584
15585 status = wlan_hdd_validate_context(pHddCtx);
15586
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015587 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015588 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015589
15590 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15591
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015592 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15593 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015594
15595 /* Add to the PMKSA ID Cache in CSR */
15596 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15597 &pmk_id, 1, false);
15598
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015599 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015600 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15601 pAdapter->sessionId, result));
15602
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015603 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015604 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015605}
15606
15607/**
15608 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15609 * @wiphy: Pointer to wiphy
15610 * @dev: Pointer to network device
15611 * @pmksa: Pointer to set pmksa parameter
15612 *
15613 * Return: 0 for success, non-zero for failure
15614 */
15615static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15616 struct net_device *dev,
15617 struct cfg80211_pmksa *pmksa)
15618{
15619 int ret;
15620
15621 cds_ssr_protect(__func__);
15622 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15623 cds_ssr_unprotect(__func__);
15624
15625 return ret;
15626}
15627
15628/**
15629 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15630 * @wiphy: Pointer to wiphy
15631 * @dev: Pointer to network device
15632 * @pmksa: Pointer to pmksa parameter
15633 *
15634 * Return: 0 for success, non-zero for failure
15635 */
15636static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15637 struct net_device *dev,
15638 struct cfg80211_pmksa *pmksa)
15639{
15640 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15641 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15642 tHalHandle halHandle;
15643 int status = 0;
15644
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015645 ENTER();
15646
Anurag Chouhan6d760662016-02-20 16:05:43 +053015647 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015648 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015649 return -EINVAL;
15650 }
15651
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015652 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15653 hdd_err("invalid session id: %d", pAdapter->sessionId);
15654 return -EINVAL;
15655 }
15656
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015657 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015658 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015659 return -EINVAL;
15660 }
15661
15662 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015663 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015664 return -EINVAL;
15665 }
15666
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015667 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015668 MAC_ADDR_ARRAY(pmksa->bssid));
15669
15670 status = wlan_hdd_validate_context(pHddCtx);
15671
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015672 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015673 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015674
15675 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15676
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015677 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015678 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15679 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015680 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015681 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015682 sme_roam_del_pmkid_from_cache(halHandle,
15683 pAdapter->sessionId, pmksa->bssid,
15684 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015685 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015686 MAC_ADDR_ARRAY(pmksa->bssid));
15687 status = -EINVAL;
15688 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015689 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015690 return status;
15691}
15692
15693/**
15694 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15695 * @wiphy: Pointer to wiphy
15696 * @dev: Pointer to network device
15697 * @pmksa: Pointer to pmksa parameter
15698 *
15699 * Return: 0 for success, non-zero for failure
15700 */
15701static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15702 struct net_device *dev,
15703 struct cfg80211_pmksa *pmksa)
15704{
15705 int ret;
15706
15707 cds_ssr_protect(__func__);
15708 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15709 cds_ssr_unprotect(__func__);
15710
15711 return ret;
15712
15713}
15714
15715/**
15716 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15717 * @wiphy: Pointer to wiphy
15718 * @dev: Pointer to network device
15719 *
15720 * Return: 0 for success, non-zero for failure
15721 */
15722static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15723 struct net_device *dev)
15724{
15725 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15726 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15727 tHalHandle halHandle;
15728 int status = 0;
15729
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015730 ENTER();
15731
Anurag Chouhan6d760662016-02-20 16:05:43 +053015732 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015733 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015734 return -EINVAL;
15735 }
15736
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015737 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15738 hdd_err("invalid session id: %d", pAdapter->sessionId);
15739 return -EINVAL;
15740 }
15741
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015742 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015743
15744 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15745 status = wlan_hdd_validate_context(pHddCtx);
15746
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015747 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015748 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015749
15750 /* Retrieve halHandle */
15751 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15752
15753 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015754 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015755 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15756 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015757 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015758 status = -EINVAL;
15759 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015760 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015761 return status;
15762}
15763
15764/**
15765 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15766 * @wiphy: Pointer to wiphy
15767 * @dev: Pointer to network device
15768 *
15769 * Return: 0 for success, non-zero for failure
15770 */
15771static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15772 struct net_device *dev)
15773{
15774 int ret;
15775
15776 cds_ssr_protect(__func__);
15777 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15778 cds_ssr_unprotect(__func__);
15779
15780 return ret;
15781}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015782
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015783#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015784/**
15785 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15786 * @wiphy: Pointer to wiphy
15787 * @dev: Pointer to network device
15788 * @ftie: Pointer to fast transition ie parameter
15789 *
15790 * Return: 0 for success, non-zero for failure
15791 */
15792static int
15793__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15794 struct net_device *dev,
15795 struct cfg80211_update_ft_ies_params *ftie)
15796{
15797 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15798 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15799 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15800 int status;
15801
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015802 ENTER();
15803
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015804 status = wlan_hdd_validate_context(hdd_ctx);
15805 if (status)
15806 return status;
15807
Anurag Chouhan6d760662016-02-20 16:05:43 +053015808 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015809 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015810 return -EINVAL;
15811 }
15812
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015813 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15814 hdd_err("invalid session id: %d", pAdapter->sessionId);
15815 return -EINVAL;
15816 }
15817
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015818 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015819 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15820 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15821 /* Added for debug on reception of Re-assoc Req. */
15822 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015823 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015824 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015825 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015826 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015827 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015828 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015829
15830 /* Pass the received FT IEs to SME */
15831 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15832 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015833 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015834 return 0;
15835}
15836
15837/**
15838 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15839 * @wiphy: Pointer to wiphy
15840 * @dev: Pointer to network device
15841 * @ftie: Pointer to fast transition ie parameter
15842 *
15843 * Return: 0 for success, non-zero for failure
15844 */
15845static int
15846wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15847 struct net_device *dev,
15848 struct cfg80211_update_ft_ies_params *ftie)
15849{
15850 int ret;
15851
15852 cds_ssr_protect(__func__);
15853 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15854 cds_ssr_unprotect(__func__);
15855
15856 return ret;
15857}
15858#endif
15859
Mukul Sharma3d36c392017-01-18 18:39:12 +053015860void wlan_hdd_cfg80211_update_replay_counter_callback(
15861 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15862
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015863{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015864 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15865 uint8_t temp_replay_counter[8];
15866 int i;
15867 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015868
15869 ENTER();
15870
Mukul Sharma3d36c392017-01-18 18:39:12 +053015871 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015872 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015873 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015874 }
15875
Mukul Sharma3d36c392017-01-18 18:39:12 +053015876 if (!gtk_rsp_param) {
15877 hdd_err("gtk_rsp_param is Null");
15878 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015879 }
15880
Mukul Sharma3d36c392017-01-18 18:39:12 +053015881 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015882 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015883 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015884 }
15885
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015886 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015887 gtk_rsp_param->replay_counter);
15888 /* convert little to big endian since supplicant works on big endian */
15889 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15890 for (i = 0; i < 8; i++)
15891 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015892
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015893 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015894 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015895 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015896 gtk_rsp_param->bssid.bytes,
15897 temp_replay_counter, GFP_KERNEL);
15898out:
15899 EXIT();
15900
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015901}
15902
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015903static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015904int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015905 struct net_device *dev,
15906 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015907{
15908 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015909 int result, i;
15910 struct pmo_gtk_req *gtk_req = NULL;
15911 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15912 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015913 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015914
15915 ENTER();
15916
Anurag Chouhan6d760662016-02-20 16:05:43 +053015917 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015918 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015919 result = -EINVAL;
15920 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015921 }
15922
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015923 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15924 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015925 result = -EINVAL;
15926 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015927 }
15928
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015929 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015930 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15931 pAdapter->sessionId, pAdapter->device_mode));
15932
Mukul Sharma3d36c392017-01-18 18:39:12 +053015933 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015934 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015935 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015936
Mukul Sharma3d36c392017-01-18 18:39:12 +053015937 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15938 if (!gtk_req) {
15939 hdd_err("cannot allocate gtk_req");
15940 result = -ENOMEM;
15941 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015942 }
15943
Mukul Sharma3d36c392017-01-18 18:39:12 +053015944 /* convert big to little endian since driver work on little endian */
15945 buf = (uint8_t *)&gtk_req->replay_counter;
15946 for (i = 0; i < 8; i++)
15947 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015948
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015949 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015950 gtk_req->replay_counter);
15951 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15952 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15953 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15954 if (status != QDF_STATUS_SUCCESS) {
15955 hdd_err("Failed to cache GTK Offload");
15956 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015957 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015958out:
15959 if (gtk_req)
15960 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015961 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015962
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015963 return result;
15964}
15965
15966/**
15967 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15968 * @wiphy: Pointer to wiphy
15969 * @dev: Pointer to network device
15970 * @data: Pointer to rekey data
15971 *
15972 * This function is used to offload GTK rekeying job to the firmware.
15973 *
15974 * Return: 0 for success, non-zero for failure
15975 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015976static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015977int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15978 struct net_device *dev,
15979 struct cfg80211_gtk_rekey_data *data)
15980{
15981 int ret;
15982
15983 cds_ssr_protect(__func__);
15984 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15985 cds_ssr_unprotect(__func__);
15986
15987 return ret;
15988}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015989
15990/**
15991 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15992 * @wiphy: Pointer to wiphy
15993 * @dev: Pointer to network device
15994 * @param: Pointer to access control parameter
15995 *
15996 * Return: 0 for success, non-zero for failure
15997 */
15998static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15999 struct net_device *dev,
16000 const struct cfg80211_acl_data *params)
16001{
16002 int i;
16003 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16004 hdd_hostapd_state_t *pHostapdState;
16005 tsap_Config_t *pConfig;
16006 v_CONTEXT_t p_cds_context = NULL;
16007 hdd_context_t *pHddCtx;
16008 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016009 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016010
16011 ENTER();
16012
Anurag Chouhan6d760662016-02-20 16:05:43 +053016013 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016014 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016015 return -EINVAL;
16016 }
16017
16018 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016019 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016020 return -EINVAL;
16021 }
16022
16023 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16024 status = wlan_hdd_validate_context(pHddCtx);
16025
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016026 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016027 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016028
16029 p_cds_context = pHddCtx->pcds_context;
16030 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16031
16032 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016033 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016034 return -EINVAL;
16035 }
16036
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016037 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016038 params->n_acl_entries);
16039
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016040 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016041 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16042 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016043 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016044 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16045
16046 /* default value */
16047 pConfig->num_accept_mac = 0;
16048 pConfig->num_deny_mac = 0;
16049
16050 /**
16051 * access control policy
16052 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16053 * listed in hostapd.deny file.
16054 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16055 * listed in hostapd.accept file.
16056 */
16057 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16058 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16059 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16060 params->acl_policy) {
16061 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16062 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016063 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016064 params->acl_policy);
16065 return -ENOTSUPP;
16066 }
16067
16068 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16069 pConfig->num_accept_mac = params->n_acl_entries;
16070 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016071 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016072 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016073 MAC_ADDR_ARRAY(
16074 params->mac_addrs[i].addr));
16075
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016076 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016077 params->mac_addrs[i].addr,
16078 sizeof(qcmacaddr));
16079 }
16080 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16081 pConfig->num_deny_mac = params->n_acl_entries;
16082 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016083 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016084 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016085 MAC_ADDR_ARRAY(
16086 params->mac_addrs[i].addr));
16087
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016088 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016089 params->mac_addrs[i].addr,
16090 sizeof(qcmacaddr));
16091 }
16092 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016093 qdf_status = wlansap_set_mac_acl(
16094 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016095 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016096 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016097 return -EINVAL;
16098 }
16099 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016100 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016101 hdd_device_mode_to_string(pAdapter->device_mode),
16102 pAdapter->device_mode);
16103 return -EINVAL;
16104 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016105 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016106 return 0;
16107}
16108
16109/**
16110 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16111 * __wlan_hdd_cfg80211_set_mac_acl
16112 * @wiphy: pointer to wiphy structure
16113 * @dev: pointer to net_device
16114 * @params: pointer to cfg80211_acl_data
16115 *
16116 * Return; 0 on success, error number otherwise
16117 */
16118static int
16119wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16120 struct net_device *dev,
16121 const struct cfg80211_acl_data *params)
16122{
16123 int ret;
16124
16125 cds_ssr_protect(__func__);
16126 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16127 cds_ssr_unprotect(__func__);
16128
16129 return ret;
16130}
16131
16132#ifdef WLAN_NL80211_TESTMODE
16133#ifdef FEATURE_WLAN_LPHB
16134/**
16135 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16136 * @pHddCtx: Pointer to hdd context
16137 * @lphbInd: Pointer to low power heart beat indication parameter
16138 *
16139 * Return: none
16140 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016141static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016142 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016143{
16144 struct sk_buff *skb;
16145
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016146 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016147
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016148 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016149 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016150
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016151 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016152 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016153 return;
16154 }
16155
16156 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016157 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016158 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016159 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160 return;
16161 }
16162
16163 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016164 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016165 goto nla_put_failure;
16166 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016167 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016168 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016169 goto nla_put_failure;
16170 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016171 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16172 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016173 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016174 goto nla_put_failure;
16175 }
16176 cfg80211_testmode_event(skb, GFP_ATOMIC);
16177 return;
16178
16179nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016180 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016181 kfree_skb(skb);
16182
16183 return;
16184}
16185#endif /* FEATURE_WLAN_LPHB */
16186
16187/**
16188 * __wlan_hdd_cfg80211_testmode() - test mode
16189 * @wiphy: Pointer to wiphy
16190 * @data: Data pointer
16191 * @len: Data length
16192 *
16193 * Return: 0 for success, non-zero for failure
16194 */
16195static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16196 void *data, int len)
16197{
16198 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16199 int err;
16200 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16201
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016202 ENTER();
16203
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016204 err = wlan_hdd_validate_context(pHddCtx);
16205 if (err)
16206 return err;
16207
16208 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16209 len, wlan_hdd_tm_policy);
16210 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016211 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016212 return err;
16213 }
16214
16215 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016216 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016217 return -EINVAL;
16218 }
16219
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016220 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016221 TRACE_CODE_HDD_CFG80211_TESTMODE,
16222 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016223 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16224#ifdef FEATURE_WLAN_LPHB
16225 /* Low Power Heartbeat configuration request */
16226 case WLAN_HDD_TM_CMD_WLAN_HB:
16227 {
16228 int buf_len;
16229 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016230 struct pmo_lphb_req *hb_params = NULL;
16231 struct pmo_lphb_req *hb_params_temp = NULL;
16232 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016233
16234 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016235 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016236 return -EINVAL;
16237 }
16238
16239 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16240 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16241
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016242 hb_params_temp = (struct pmo_lphb_req *) buf;
16243 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16244 && (hb_params_temp->params.lphb_tcp_params.
16245 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016246 return -EINVAL;
16247
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016248 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16249 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016250 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016251 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016252 return -ENOMEM;
16253 }
16254
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016255 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016256 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16257 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016258 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016259 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016260 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016261
16262 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016263 return 0;
16264 }
16265#endif /* FEATURE_WLAN_LPHB */
16266
16267#if defined(QCA_WIFI_FTM)
16268 case WLAN_HDD_TM_CMD_WLAN_FTM:
16269 {
16270 int buf_len;
16271 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016272 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016274 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016275 return -EINVAL;
16276 }
16277
16278 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16279 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16280
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016281 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016282
16283 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16284
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016285 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016286 err = -EBUSY;
16287 break;
16288 }
16289#endif
16290
16291 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016292 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016293 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16294 return -EOPNOTSUPP;
16295 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016296 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016297 return err;
16298}
16299
16300/**
16301 * wlan_hdd_cfg80211_testmode() - test mode
16302 * @wiphy: Pointer to wiphy
16303 * @dev: Pointer to network device
16304 * @data: Data pointer
16305 * @len: Data length
16306 *
16307 * Return: 0 for success, non-zero for failure
16308 */
16309static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16310#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16311 struct wireless_dev *wdev,
16312#endif
16313 void *data, int len)
16314{
16315 int ret;
16316
16317 cds_ssr_protect(__func__);
16318 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16319 cds_ssr_unprotect(__func__);
16320
16321 return ret;
16322}
16323
16324#if defined(QCA_WIFI_FTM)
16325/**
16326 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16327 * @buf: Pointer to buffer
16328 * @buf_len: Buffer length
16329 *
16330 * Return: none
16331 */
16332void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16333{
16334 struct sk_buff *skb;
16335 hdd_context_t *hdd_ctx;
16336
16337 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016338 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016339 return;
16340 }
16341
Anurag Chouhan6d760662016-02-20 16:05:43 +053016342 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016343 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016344 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016345 return;
16346 }
16347
16348 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16349 buf_len, GFP_KERNEL);
16350 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016351 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016352 return;
16353 }
16354
16355 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16356 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16357 goto nla_put_failure;
16358
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016359 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016360
16361 cfg80211_testmode_event(skb, GFP_KERNEL);
16362 return;
16363
16364nla_put_failure:
16365 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016366 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016367}
16368#endif
16369#endif /* CONFIG_NL80211_TESTMODE */
16370
16371#ifdef QCA_HT_2040_COEX
16372/**
16373 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16374 * @wiphy: Pointer to wiphy
16375 * @dev: Pointer to network device
16376 * @chandef: Pointer to channel definition parameter
16377 *
16378 * Return: 0 for success, non-zero for failure
16379 */
16380static int
16381__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16382 struct net_device *dev,
16383 struct cfg80211_chan_def *chandef)
16384{
16385 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16386 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016387 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016388 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016389 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016390
Anurag Chouhan6d760662016-02-20 16:05:43 +053016391 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016392 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016393 return -EINVAL;
16394 }
16395
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016396 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16397 hdd_err("invalid session id: %d", pAdapter->sessionId);
16398 return -EINVAL;
16399 }
16400
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016401 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16402 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016403 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016404 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016405
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016406 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016407 sme_get_config_param(pHddCtx->hHal, &sme_config);
16408 switch (chandef->width) {
16409 case NL80211_CHAN_WIDTH_20:
16410 if (sme_config.csrConfig.channelBondingMode24GHz !=
16411 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16412 sme_config.csrConfig.channelBondingMode24GHz =
16413 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16414 sme_update_config(pHddCtx->hHal, &sme_config);
16415 cbModeChange = true;
16416 }
16417 break;
16418
16419 case NL80211_CHAN_WIDTH_40:
16420 if (sme_config.csrConfig.channelBondingMode24GHz ==
16421 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16422 if (NL80211_CHAN_HT40MINUS ==
16423 cfg80211_get_chandef_type(chandef))
16424 sme_config.csrConfig.channelBondingMode24GHz =
16425 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16426 else
16427 sme_config.csrConfig.channelBondingMode24GHz =
16428 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16429 sme_update_config(pHddCtx->hHal, &sme_config);
16430 cbModeChange = true;
16431 }
16432 break;
16433
16434 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016435 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016436 return -EINVAL;
16437 }
16438
16439 if (!cbModeChange)
16440 return 0;
16441
Krunal Sonib4326f22016-03-10 13:05:51 -080016442 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016443 return 0;
16444
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016445 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016446 sme_config.csrConfig.channelBondingMode24GHz);
16447
16448 /* Change SAP ht2040 mode */
16449 status = hdd_set_sap_ht2040_mode(pAdapter,
16450 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016451 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016452 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016453 return -EINVAL;
16454 }
16455
16456 return 0;
16457}
16458
16459/**
16460 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16461 * @wiphy: Pointer to wiphy
16462 * @dev: Pointer to network device
16463 * @chandef: Pointer to channel definition parameter
16464 *
16465 * Return: 0 for success, non-zero for failure
16466 */
16467static int
16468wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16469 struct net_device *dev,
16470 struct cfg80211_chan_def *chandef)
16471{
16472 int ret;
16473
16474 cds_ssr_protect(__func__);
16475 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16476 cds_ssr_unprotect(__func__);
16477
16478 return ret;
16479}
16480#endif
16481
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016482#ifdef CHANNEL_SWITCH_SUPPORTED
16483/**
16484 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16485 * channel in SAP/GO
16486 * @wiphy: wiphy pointer
16487 * @dev: dev pointer.
16488 * @csa_params: Change channel params
16489 *
16490 * This function is called to switch channel in SAP/GO
16491 *
16492 * Return: 0 if success else return non zero
16493 */
16494static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16495 struct net_device *dev,
16496 struct cfg80211_csa_settings *csa_params)
16497{
16498 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16499 hdd_context_t *hdd_ctx;
16500 uint8_t channel;
16501 uint16_t freq;
16502 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016503 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016504
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016505 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016506 csa_params->chandef.chan->center_freq);
16507
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016508 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16509 hdd_err("invalid session id: %d", adapter->sessionId);
16510 return -EINVAL;
16511 }
16512
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016513 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16514 ret = wlan_hdd_validate_context(hdd_ctx);
16515
16516 if (0 != ret)
16517 return ret;
16518
Krunal Sonib4326f22016-03-10 13:05:51 -080016519 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16520 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016521 return -ENOTSUPP;
16522
16523 freq = csa_params->chandef.chan->center_freq;
16524 channel = cds_freq_to_chan(freq);
16525
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016526 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16527
16528 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016529 return ret;
16530}
16531
16532/**
16533 * wlan_hdd_cfg80211_channel_switch()- function to switch
16534 * channel in SAP/GO
16535 * @wiphy: wiphy pointer
16536 * @dev: dev pointer.
16537 * @csa_params: Change channel params
16538 *
16539 * This function is called to switch channel in SAP/GO
16540 *
16541 * Return: 0 if success else return non zero
16542 */
16543static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16544 struct net_device *dev,
16545 struct cfg80211_csa_settings *csa_params)
16546{
16547 int ret;
16548
16549 cds_ssr_protect(__func__);
16550 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16551 cds_ssr_unprotect(__func__);
16552 return ret;
16553}
16554#endif
16555
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016556/**
16557 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16558 * translation from NL to policy manager type
16559 * @type: Generic connection mode type defined in NL
16560 *
16561 *
16562 * This function provides the type translation
16563 *
16564 * Return: cds_con_mode enum
16565 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016566enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016567 enum nl80211_iftype type)
16568{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016569 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016570 switch (type) {
16571 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016572 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016573 break;
16574 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016575 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016576 break;
16577 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016578 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016579 break;
16580 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016581 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016582 break;
16583 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016584 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016585 break;
16586 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016587 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016588 }
16589 return mode;
16590}
16591
16592/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016593 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16594 * @wiphy: Handle to struct wiphy to get handle to module context.
16595 * @chandef: Contains information about the capture channel to be set.
16596 *
16597 * This interface is called if and only if monitor mode interface alone is
16598 * active.
16599 *
16600 * Return: 0 success or error code on failure.
16601 */
16602static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16603 struct cfg80211_chan_def *chandef)
16604{
16605 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16606 hdd_adapter_t *adapter;
16607 hdd_station_ctx_t *sta_ctx;
16608 struct hdd_mon_set_ch_info *ch_info;
16609 QDF_STATUS status;
16610 tHalHandle hal_hdl;
16611 struct qdf_mac_addr bssid;
16612 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016613 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016614 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016615 int ret;
16616 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16617
16618 ENTER();
16619
16620 ret = wlan_hdd_validate_context(hdd_ctx);
16621 if (ret)
16622 return ret;
16623
16624 hal_hdl = hdd_ctx->hHal;
16625
16626 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16627 if (!adapter)
16628 return -EIO;
16629
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016630 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016631 adapter->dev->name, chan_num, chandef->chan->center_freq);
16632
16633 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16634 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016635 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16636 roam_profile.ChannelInfo.numOfChannels = 1;
16637 roam_profile.phyMode = ch_info->phy_mode;
16638 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016639 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016640
16641 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16642 QDF_MAC_ADDR_SIZE);
16643
16644 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016645 /*
16646 * CDS api expects secondary channel for calculating
16647 * the channel params
16648 */
16649 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16650 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16651 if (chan_num >= 1 && chan_num <= 5)
16652 sec_ch = chan_num + 4;
16653 else if (chan_num >= 6 && chan_num <= 13)
16654 sec_ch = chan_num - 4;
16655 }
16656 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016657 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16658 &roam_profile);
16659 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016660 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016661 status);
16662 ret = qdf_status_to_os_return(status);
16663 return ret;
16664 }
16665 EXIT();
16666 return 0;
16667}
16668
16669/**
16670 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16671 * @wiphy: Handle to struct wiphy to get handle to module context.
16672 * @chandef: Contains information about the capture channel to be set.
16673 *
16674 * This interface is called if and only if monitor mode interface alone is
16675 * active.
16676 *
16677 * Return: 0 success or error code on failure.
16678 */
16679static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16680 struct cfg80211_chan_def *chandef)
16681{
16682 int ret;
16683
16684 cds_ssr_protect(__func__);
16685 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16686 cds_ssr_unprotect(__func__);
16687 return ret;
16688}
16689
16690/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016691 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16692 * @adapter: pointer to adapter
16693 *
16694 * Wrapper function to clear link layer stats.
16695 * return - void
16696 */
16697void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16698{
16699 tSirLLStatsClearReq link_layer_stats_clear_req;
16700 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16701
Mukul Sharma491021c2016-09-29 21:39:19 +053016702 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16703 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016704 link_layer_stats_clear_req.stopReq = 0;
16705 link_layer_stats_clear_req.reqId = 1;
16706 link_layer_stats_clear_req.staId = adapter->sessionId;
16707 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16708
16709 return;
16710}
16711
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016712/**
16713 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16714 * @adapter: HDD Adapter
16715 *
16716 * If roaming is in progress and there is a request to
16717 * disconnect the session, then it is deferred. Once
16718 * roaming is complete/aborted, then this routine is
16719 * used to resume the disconnect that was deferred
16720 *
16721 * Return: None
16722 */
16723void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16724{
16725 switch (adapter->defer_disconnect) {
16726 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16727 adapter->defer_disconnect = 0;
16728 wlan_hdd_disconnect(adapter,
16729 adapter->cfg80211_disconnect_reason);
16730 break;
16731 case DEFER_DISCONNECT_TRY_DISCONNECT:
16732 wlan_hdd_try_disconnect(adapter);
16733 adapter->defer_disconnect = 0;
16734 break;
16735 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016736 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016737 adapter->defer_disconnect);
16738 break;
16739 }
16740}
16741
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016742#define CNT_DIFF(cur, prev) \
16743 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16744#define MAX_COUNT 0xffffffff
16745static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16746 struct scan_chan_info *chan,
16747 struct scan_chan_info *info, uint32_t cmd_flag)
16748{
16749 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16750 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16751 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16752
16753 mutex_lock(&hdd_ctx->chan_info_lock);
16754
16755 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16756 qdf_mem_zero(chan, sizeof(*chan));
16757
16758 chan->freq = info->freq;
16759 chan->noise_floor = info->noise_floor;
16760 chan->clock_freq = info->clock_freq;
16761 chan->cmd_flag = info->cmd_flag;
16762 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16763
16764 chan->rx_clear_count =
16765 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16766
16767 chan->tx_frame_count =
16768 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16769
16770 mutex_unlock(&hdd_ctx->chan_info_lock);
16771
16772}
16773#undef CNT_DIFF
16774#undef MAX_COUNT
16775
16776/**
16777 * wlan_hdd_chan_info_cb() - channel info callback
16778 * @chan_info: struct scan_chan_info
16779 *
16780 * Store channel info into HDD context
16781 *
16782 * Return: None.
16783 */
16784static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16785{
16786 hdd_context_t *hdd_ctx;
16787 struct scan_chan_info *chan;
16788 uint8_t idx;
16789
16790 ENTER();
16791
16792 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16793 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16794 hdd_err("hdd_ctx is invalid");
16795 return;
16796 }
16797
16798 if (!hdd_ctx->chan_info) {
16799 hdd_err("chan_info is NULL");
16800 return;
16801 }
16802
16803 chan = hdd_ctx->chan_info;
16804 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16805 if (chan[idx].freq == info->freq) {
16806 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16807 info->cmd_flag);
16808 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16809 chan[idx].cmd_flag, chan[idx].freq,
16810 chan[idx].noise_floor,
16811 chan[idx].cycle_count, chan[idx].rx_clear_count,
16812 chan[idx].clock_freq, chan[idx].cmd_flag,
16813 chan[idx].tx_frame_count, idx);
16814 if (chan[idx].freq == 0)
16815 break;
16816
16817 }
16818 }
16819
16820 EXIT();
16821}
16822
16823/**
16824 * wlan_hdd_init_chan_info() - init chan info in hdd context
16825 * @hdd_ctx: HDD context pointer
16826 *
16827 * Return: none
16828 */
16829void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16830{
16831 uint8_t num_2g, num_5g, index = 0;
16832
16833 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16834 hdd_info("SNR monitoring is disabled");
16835 return;
16836 }
16837
16838 hdd_ctx->chan_info =
16839 qdf_mem_malloc(sizeof(struct scan_chan_info)
16840 * QDF_MAX_NUM_CHAN);
16841 if (hdd_ctx->chan_info == NULL) {
16842 hdd_err("Failed to malloc for chan info");
16843 return;
16844 }
16845 mutex_init(&hdd_ctx->chan_info_lock);
16846
16847 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16848 for (; index < num_2g; index++) {
16849 hdd_ctx->chan_info[index].freq =
16850 hdd_channels_2_4_ghz[index].center_freq;
16851 }
16852
16853 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16854 for (; (index - num_2g) < num_5g; index++) {
16855 if (cds_is_dsrc_channel(
16856 hdd_channels_5_ghz[index - num_2g].center_freq))
16857 continue;
16858 hdd_ctx->chan_info[index].freq =
16859 hdd_channels_5_ghz[index - num_2g].center_freq;
16860 }
16861 sme_set_chan_info_callback(hdd_ctx->hHal,
16862 &wlan_hdd_chan_info_cb);
16863}
16864
16865/**
16866 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16867 * @hdd_ctx: hdd context pointer
16868 *
16869 * Return: none
16870 */
16871void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16872{
16873 struct scan_chan_info *chan;
16874
16875 chan = hdd_ctx->chan_info;
16876 hdd_ctx->chan_info = NULL;
16877 if (chan)
16878 qdf_mem_free(chan);
16879}
16880
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016881/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016882 * struct cfg80211_ops - cfg80211_ops
16883 *
16884 * @add_virtual_intf: Add virtual interface
16885 * @del_virtual_intf: Delete virtual interface
16886 * @change_virtual_intf: Change virtual interface
16887 * @change_station: Change station
16888 * @add_beacon: Add beacon in sap mode
16889 * @del_beacon: Delete beacon in sap mode
16890 * @set_beacon: Set beacon in sap mode
16891 * @start_ap: Start ap
16892 * @change_beacon: Change beacon
16893 * @stop_ap: Stop ap
16894 * @change_bss: Change bss
16895 * @add_key: Add key
16896 * @get_key: Get key
16897 * @del_key: Delete key
16898 * @set_default_key: Set default key
16899 * @set_channel: Set channel
16900 * @scan: Scan
16901 * @connect: Connect
16902 * @disconnect: Disconnect
16903 * @join_ibss = Join ibss
16904 * @leave_ibss = Leave ibss
16905 * @set_wiphy_params = Set wiphy params
16906 * @set_tx_power = Set tx power
16907 * @get_tx_power = get tx power
16908 * @remain_on_channel = Remain on channel
16909 * @cancel_remain_on_channel = Cancel remain on channel
16910 * @mgmt_tx = Tx management frame
16911 * @mgmt_tx_cancel_wait = Cancel management tx wait
16912 * @set_default_mgmt_key = Set default management key
16913 * @set_txq_params = Set tx queue parameters
16914 * @get_station = Get station
16915 * @set_power_mgmt = Set power management
16916 * @del_station = Delete station
16917 * @add_station = Add station
16918 * @set_pmksa = Set pmksa
16919 * @del_pmksa = Delete pmksa
16920 * @flush_pmksa = Flush pmksa
16921 * @update_ft_ies = Update FT IEs
16922 * @tdls_mgmt = Tdls management
16923 * @tdls_oper = Tdls operation
16924 * @set_rekey_data = Set rekey data
16925 * @sched_scan_start = Scheduled scan start
16926 * @sched_scan_stop = Scheduled scan stop
16927 * @resume = Resume wlan
16928 * @suspend = Suspend wlan
16929 * @set_mac_acl = Set mac acl
16930 * @testmode_cmd = Test mode command
16931 * @set_ap_chanwidth = Set AP channel bandwidth
16932 * @dump_survey = Dump survey
16933 * @key_mgmt_set_pmk = Set pmk key management
16934 */
16935static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16936 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16937 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16938 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16939 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016940 .start_ap = wlan_hdd_cfg80211_start_ap,
16941 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16942 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016943 .change_bss = wlan_hdd_cfg80211_change_bss,
16944 .add_key = wlan_hdd_cfg80211_add_key,
16945 .get_key = wlan_hdd_cfg80211_get_key,
16946 .del_key = wlan_hdd_cfg80211_del_key,
16947 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16948 .scan = wlan_hdd_cfg80211_scan,
16949 .connect = wlan_hdd_cfg80211_connect,
16950 .disconnect = wlan_hdd_cfg80211_disconnect,
16951 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16952 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16953 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16954 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16955 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16956 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16957 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16958 .mgmt_tx = wlan_hdd_mgmt_tx,
16959 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16960 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16961 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016962 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016963 .get_station = wlan_hdd_cfg80211_get_station,
16964 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16965 .del_station = wlan_hdd_cfg80211_del_station,
16966 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016967 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16968 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16969 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016970#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016971 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16972#endif
16973#ifdef FEATURE_WLAN_TDLS
16974 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16975 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16976#endif
16977#ifdef WLAN_FEATURE_GTK_OFFLOAD
16978 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16979#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16980#ifdef FEATURE_WLAN_SCAN_PNO
16981 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16982 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16983#endif /*FEATURE_WLAN_SCAN_PNO */
16984 .resume = wlan_hdd_cfg80211_resume_wlan,
16985 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16986 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16987#ifdef WLAN_NL80211_TESTMODE
16988 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16989#endif
16990#ifdef QCA_HT_2040_COEX
16991 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16992#endif
16993 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016994#ifdef CHANNEL_SWITCH_SUPPORTED
16995 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16996#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016997 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016998#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16999 defined(CFG80211_ABORT_SCAN)
17000 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17001#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017002};