blob: f1de64c721326ce7f288475a258bf6e7cc4a0f28 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080081#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080082#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083
84#ifdef FEATURE_WLAN_EXTSCAN
85#include "wlan_hdd_ext_scan.h"
86#endif
87
88#ifdef WLAN_FEATURE_LINK_LAYER_STATS
89#include "wlan_hdd_stats.h"
90#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080091#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080092#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#include "qwlan_version.h"
94#include "wlan_hdd_memdump.h"
95
96#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070097#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +0530100#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700101#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700102#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530103#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800104#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800105#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800106
Leo Changfdb45c32016-10-28 11:09:23 -0700107#include <cdp_txrx_cmn.h>
108#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800109#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530110#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800111#include "os_if_wifi_pos.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700112
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113#define g_mode_rates_size (12)
114#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
116 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
117
118/*
119 * Android CTS verifier needs atleast this much wait time (in msec)
120 */
121#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
122
123/*
124 * Refer @tCfgProtection structure for definition of the bit map.
125 * below value is obtained by setting the following bit-fields.
126 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
127 */
128#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
129
130#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700131 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800132 .center_freq = (freq), \
133 .hw_value = (chan), \
134 .flags = (flag), \
135 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800136 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800137}
138
139#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700140 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800141 .center_freq = (freq), \
142 .hw_value = (chan), \
143 .flags = (flag), \
144 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800145 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800146}
147
148#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
149 { \
150 .bitrate = rate, \
151 .hw_value = rate_id, \
152 .flags = flag, \
153 }
154
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
156#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157
158#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159
Agrawal Ashish65634612016-08-18 13:24:32 +0530160#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
161 mode <= DFS_MODE_DEPRIORITIZE))
162#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
163 || (channel >= 36 && channel <= 184))
164
Peng Xu4d67c8f2015-10-16 16:02:26 -0700165#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530166#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168static const u32 hdd_cipher_suites[] = {
169 WLAN_CIPHER_SUITE_WEP40,
170 WLAN_CIPHER_SUITE_WEP104,
171 WLAN_CIPHER_SUITE_TKIP,
172#ifdef FEATURE_WLAN_ESE
173#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
174#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
175 WLAN_CIPHER_SUITE_BTK,
176 WLAN_CIPHER_SUITE_KRK,
177 WLAN_CIPHER_SUITE_CCMP,
178#else
179 WLAN_CIPHER_SUITE_CCMP,
180#endif
181#ifdef FEATURE_WLAN_WAPI
182 WLAN_CIPHER_SUITE_SMS4,
183#endif
184#ifdef WLAN_FEATURE_11W
185 WLAN_CIPHER_SUITE_AES_CMAC,
186#endif
187};
188
Abhishek Singhf512bf32016-05-04 16:47:46 +0530189static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800190 HDD2GHZCHAN(2412, 1, 0),
191 HDD2GHZCHAN(2417, 2, 0),
192 HDD2GHZCHAN(2422, 3, 0),
193 HDD2GHZCHAN(2427, 4, 0),
194 HDD2GHZCHAN(2432, 5, 0),
195 HDD2GHZCHAN(2437, 6, 0),
196 HDD2GHZCHAN(2442, 7, 0),
197 HDD2GHZCHAN(2447, 8, 0),
198 HDD2GHZCHAN(2452, 9, 0),
199 HDD2GHZCHAN(2457, 10, 0),
200 HDD2GHZCHAN(2462, 11, 0),
201 HDD2GHZCHAN(2467, 12, 0),
202 HDD2GHZCHAN(2472, 13, 0),
203 HDD2GHZCHAN(2484, 14, 0),
204};
205
Abhishek Singhf512bf32016-05-04 16:47:46 +0530206static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800207 HDD5GHZCHAN(5180, 36, 0),
208 HDD5GHZCHAN(5200, 40, 0),
209 HDD5GHZCHAN(5220, 44, 0),
210 HDD5GHZCHAN(5240, 48, 0),
211 HDD5GHZCHAN(5260, 52, 0),
212 HDD5GHZCHAN(5280, 56, 0),
213 HDD5GHZCHAN(5300, 60, 0),
214 HDD5GHZCHAN(5320, 64, 0),
215 HDD5GHZCHAN(5500, 100, 0),
216 HDD5GHZCHAN(5520, 104, 0),
217 HDD5GHZCHAN(5540, 108, 0),
218 HDD5GHZCHAN(5560, 112, 0),
219 HDD5GHZCHAN(5580, 116, 0),
220 HDD5GHZCHAN(5600, 120, 0),
221 HDD5GHZCHAN(5620, 124, 0),
222 HDD5GHZCHAN(5640, 128, 0),
223 HDD5GHZCHAN(5660, 132, 0),
224 HDD5GHZCHAN(5680, 136, 0),
225 HDD5GHZCHAN(5700, 140, 0),
226 HDD5GHZCHAN(5720, 144, 0),
227 HDD5GHZCHAN(5745, 149, 0),
228 HDD5GHZCHAN(5765, 153, 0),
229 HDD5GHZCHAN(5785, 157, 0),
230 HDD5GHZCHAN(5805, 161, 0),
231 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800232 HDD5GHZCHAN(5852, 170, 0),
233 HDD5GHZCHAN(5855, 171, 0),
234 HDD5GHZCHAN(5860, 172, 0),
235 HDD5GHZCHAN(5865, 173, 0),
236 HDD5GHZCHAN(5870, 174, 0),
237 HDD5GHZCHAN(5875, 175, 0),
238 HDD5GHZCHAN(5880, 176, 0),
239 HDD5GHZCHAN(5885, 177, 0),
240 HDD5GHZCHAN(5890, 178, 0),
241 HDD5GHZCHAN(5895, 179, 0),
242 HDD5GHZCHAN(5900, 180, 0),
243 HDD5GHZCHAN(5905, 181, 0),
244 HDD5GHZCHAN(5910, 182, 0),
245 HDD5GHZCHAN(5915, 183, 0),
246 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800247};
248
249static struct ieee80211_rate g_mode_rates[] = {
250 HDD_G_MODE_RATETAB(10, 0x1, 0),
251 HDD_G_MODE_RATETAB(20, 0x2, 0),
252 HDD_G_MODE_RATETAB(55, 0x4, 0),
253 HDD_G_MODE_RATETAB(110, 0x8, 0),
254 HDD_G_MODE_RATETAB(60, 0x10, 0),
255 HDD_G_MODE_RATETAB(90, 0x20, 0),
256 HDD_G_MODE_RATETAB(120, 0x40, 0),
257 HDD_G_MODE_RATETAB(180, 0x80, 0),
258 HDD_G_MODE_RATETAB(240, 0x100, 0),
259 HDD_G_MODE_RATETAB(360, 0x200, 0),
260 HDD_G_MODE_RATETAB(480, 0x400, 0),
261 HDD_G_MODE_RATETAB(540, 0x800, 0),
262};
263
264static struct ieee80211_rate a_mode_rates[] = {
265 HDD_G_MODE_RATETAB(60, 0x10, 0),
266 HDD_G_MODE_RATETAB(90, 0x20, 0),
267 HDD_G_MODE_RATETAB(120, 0x40, 0),
268 HDD_G_MODE_RATETAB(180, 0x80, 0),
269 HDD_G_MODE_RATETAB(240, 0x100, 0),
270 HDD_G_MODE_RATETAB(360, 0x200, 0),
271 HDD_G_MODE_RATETAB(480, 0x400, 0),
272 HDD_G_MODE_RATETAB(540, 0x800, 0),
273};
274
275static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530276 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800277 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700278 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 .bitrates = g_mode_rates,
280 .n_bitrates = g_mode_rates_size,
281 .ht_cap.ht_supported = 1,
282 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
283 | IEEE80211_HT_CAP_GRN_FLD
284 | IEEE80211_HT_CAP_DSSSCCK40
285 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
286 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
287 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
288 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
289 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
290 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
291 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
292};
293
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800294static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530295 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700297 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800298 .bitrates = a_mode_rates,
299 .n_bitrates = a_mode_rates_size,
300 .ht_cap.ht_supported = 1,
301 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
302 | IEEE80211_HT_CAP_GRN_FLD
303 | IEEE80211_HT_CAP_DSSSCCK40
304 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
305 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
306 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
307 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
308 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
309 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
310 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
311 .vht_cap.vht_supported = 1,
312};
313
314/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800315 * TX/RX direction for each kind of interface
316 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800317static const struct ieee80211_txrx_stypes
318 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
319 [NL80211_IFTYPE_STATION] = {
320 .tx = 0xffff,
321 .rx = BIT(SIR_MAC_MGMT_ACTION) |
322 BIT(SIR_MAC_MGMT_PROBE_REQ),
323 },
324 [NL80211_IFTYPE_AP] = {
325 .tx = 0xffff,
326 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
328 BIT(SIR_MAC_MGMT_PROBE_REQ) |
329 BIT(SIR_MAC_MGMT_DISASSOC) |
330 BIT(SIR_MAC_MGMT_AUTH) |
331 BIT(SIR_MAC_MGMT_DEAUTH) |
332 BIT(SIR_MAC_MGMT_ACTION),
333 },
334 [NL80211_IFTYPE_ADHOC] = {
335 .tx = 0xffff,
336 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
338 BIT(SIR_MAC_MGMT_PROBE_REQ) |
339 BIT(SIR_MAC_MGMT_DISASSOC) |
340 BIT(SIR_MAC_MGMT_AUTH) |
341 BIT(SIR_MAC_MGMT_DEAUTH) |
342 BIT(SIR_MAC_MGMT_ACTION),
343 },
344 [NL80211_IFTYPE_P2P_CLIENT] = {
345 .tx = 0xffff,
346 .rx = BIT(SIR_MAC_MGMT_ACTION) |
347 BIT(SIR_MAC_MGMT_PROBE_REQ),
348 },
349 [NL80211_IFTYPE_P2P_GO] = {
350 /* This is also same as for SoftAP */
351 .tx = 0xffff,
352 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
353 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
354 BIT(SIR_MAC_MGMT_PROBE_REQ) |
355 BIT(SIR_MAC_MGMT_DISASSOC) |
356 BIT(SIR_MAC_MGMT_AUTH) |
357 BIT(SIR_MAC_MGMT_DEAUTH) |
358 BIT(SIR_MAC_MGMT_ACTION),
359 },
360};
361
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800362/* Interface limits and combinations registered by the driver */
363
364/* STA ( + STA ) combination */
365static const struct ieee80211_iface_limit
366 wlan_hdd_sta_iface_limit[] = {
367 {
368 .max = 3, /* p2p0 is a STA as well */
369 .types = BIT(NL80211_IFTYPE_STATION),
370 },
371};
372
373/* ADHOC (IBSS) limit */
374static const struct ieee80211_iface_limit
375 wlan_hdd_adhoc_iface_limit[] = {
376 {
377 .max = 1,
378 .types = BIT(NL80211_IFTYPE_STATION),
379 },
380 {
381 .max = 1,
382 .types = BIT(NL80211_IFTYPE_ADHOC),
383 },
384};
385
386/* AP ( + AP ) combination */
387static const struct ieee80211_iface_limit
388 wlan_hdd_ap_iface_limit[] = {
389 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530390 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 .types = BIT(NL80211_IFTYPE_AP),
392 },
393};
394
395/* P2P limit */
396static const struct ieee80211_iface_limit
397 wlan_hdd_p2p_iface_limit[] = {
398 {
399 .max = 1,
400 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
401 },
402 {
403 .max = 1,
404 .types = BIT(NL80211_IFTYPE_P2P_GO),
405 },
406};
407
408static const struct ieee80211_iface_limit
409 wlan_hdd_sta_ap_iface_limit[] = {
410 {
411 /* We need 1 extra STA interface for OBSS scan when SAP starts
412 * with HT40 in STA+SAP concurrency mode
413 */
414 .max = (1 + SAP_MAX_OBSS_STA_CNT),
415 .types = BIT(NL80211_IFTYPE_STATION),
416 },
417 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530418 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800419 .types = BIT(NL80211_IFTYPE_AP),
420 },
421};
422
423/* STA + P2P combination */
424static const struct ieee80211_iface_limit
425 wlan_hdd_sta_p2p_iface_limit[] = {
426 {
427 /* One reserved for dedicated P2PDEV usage */
428 .max = 2,
429 .types = BIT(NL80211_IFTYPE_STATION)
430 },
431 {
432 /* Support for two identical (GO + GO or CLI + CLI)
433 * or dissimilar (GO + CLI) P2P interfaces
434 */
435 .max = 2,
436 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
437 },
438};
439
440/* STA + AP + P2PGO combination */
441static const struct ieee80211_iface_limit
442wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
443 /* Support for AP+P2PGO interfaces */
444 {
445 .max = 2,
446 .types = BIT(NL80211_IFTYPE_STATION)
447 },
448 {
449 .max = 1,
450 .types = BIT(NL80211_IFTYPE_P2P_GO)
451 },
452 {
453 .max = 1,
454 .types = BIT(NL80211_IFTYPE_AP)
455 }
456};
457
458/* SAP + P2P combination */
459static const struct ieee80211_iface_limit
460wlan_hdd_sap_p2p_iface_limit[] = {
461 {
462 /* 1 dedicated for p2p0 which is a STA type */
463 .max = 1,
464 .types = BIT(NL80211_IFTYPE_STATION)
465 },
466 {
467 /* The p2p interface in SAP+P2P can be GO/CLI.
468 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
469 */
470 .max = 1,
471 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
472 },
473 {
474 /* SAP+GO to support only one SAP interface */
475 .max = 1,
476 .types = BIT(NL80211_IFTYPE_AP)
477 }
478};
479
480/* P2P + P2P combination */
481static const struct ieee80211_iface_limit
482wlan_hdd_p2p_p2p_iface_limit[] = {
483 {
484 /* 1 dedicated for p2p0 which is a STA type */
485 .max = 1,
486 .types = BIT(NL80211_IFTYPE_STATION)
487 },
488 {
489 /* The p2p interface in P2P+P2P can be GO/CLI.
490 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
491 */
492 .max = 2,
493 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
494 },
495};
496
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700497static const struct ieee80211_iface_limit
498 wlan_hdd_mon_iface_limit[] = {
499 {
500 .max = 3, /* Monitor interface */
501 .types = BIT(NL80211_IFTYPE_MONITOR),
502 },
503};
504
505static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800506 wlan_hdd_iface_combination[] = {
507 /* STA */
508 {
509 .limits = wlan_hdd_sta_iface_limit,
510 .num_different_channels = 2,
511 .max_interfaces = 3,
512 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
513 },
514 /* ADHOC */
515 {
516 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700517 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 .max_interfaces = 2,
519 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
520 },
521 /* AP */
522 {
523 .limits = wlan_hdd_ap_iface_limit,
524 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530525 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
527 },
528 /* P2P */
529 {
530 .limits = wlan_hdd_p2p_iface_limit,
531 .num_different_channels = 2,
532 .max_interfaces = 2,
533 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
534 },
535 /* STA + AP */
536 {
537 .limits = wlan_hdd_sta_ap_iface_limit,
538 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530539 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800540 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
541 .beacon_int_infra_match = true,
542 },
543 /* STA + P2P */
544 {
545 .limits = wlan_hdd_sta_p2p_iface_limit,
546 .num_different_channels = 2,
547 /* one interface reserved for P2PDEV dedicated usage */
548 .max_interfaces = 4,
549 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
550 .beacon_int_infra_match = true,
551 },
552 /* STA + P2P GO + SAP */
553 {
554 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
555 /* we can allow 3 channels for three different persona
556 * but due to firmware limitation, allow max 2 concrnt channels.
557 */
558 .num_different_channels = 2,
559 /* one interface reserved for P2PDEV dedicated usage */
560 .max_interfaces = 4,
561 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
562 .beacon_int_infra_match = true,
563 },
564 /* SAP + P2P */
565 {
566 .limits = wlan_hdd_sap_p2p_iface_limit,
567 .num_different_channels = 2,
568 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
569 .max_interfaces = 3,
570 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
571 .beacon_int_infra_match = true,
572 },
573 /* P2P + P2P */
574 {
575 .limits = wlan_hdd_p2p_p2p_iface_limit,
576 .num_different_channels = 2,
577 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
578 .max_interfaces = 3,
579 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
580 .beacon_int_infra_match = true,
581 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530582 /* Monitor */
583 {
584 .limits = wlan_hdd_mon_iface_limit,
585 .max_interfaces = 3,
586 .num_different_channels = 2,
587 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
588 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800589};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590
591static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592
593#ifdef WLAN_NL80211_TESTMODE
594enum wlan_hdd_tm_attr {
595 WLAN_HDD_TM_ATTR_INVALID = 0,
596 WLAN_HDD_TM_ATTR_CMD = 1,
597 WLAN_HDD_TM_ATTR_DATA = 2,
598 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
599 WLAN_HDD_TM_ATTR_TYPE = 4,
600 /* keep last */
601 WLAN_HDD_TM_ATTR_AFTER_LAST,
602 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
603};
604
605enum wlan_hdd_tm_cmd {
606 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
607 WLAN_HDD_TM_CMD_WLAN_HB = 1,
608};
609
610#define WLAN_HDD_TM_DATA_MAX_LEN 5000
611
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530612enum wlan_hdd_vendor_ie_access_policy {
613 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
614 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
615};
616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
618 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
619 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
620 .len = WLAN_HDD_TM_DATA_MAX_LEN},
621};
622#endif /* WLAN_NL80211_TESTMODE */
623
624#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
625static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
626 .flags = WIPHY_WOWLAN_MAGIC_PKT,
627 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
628 .pattern_min_len = 1,
629 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
630};
631#endif
632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800633/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530634 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
635 * @flags: Pointer to the flags to Add channel switch flag.
636 *
637 * This Function adds Channel Switch support flag, if channel switch is
638 * supported by kernel.
639 * Return: void.
640 */
641#ifdef CHANNEL_SWITCH_SUPPORTED
642static inline void hdd_add_channel_switch_support(uint32_t *flags)
643{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800644 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530645 return;
646}
647#else
648static inline void hdd_add_channel_switch_support(uint32_t *flags)
649{
650 return;
651}
652#endif
653
Manikandan Mohan22b83722015-12-15 15:03:23 -0800654#ifdef FEATURE_WLAN_TDLS
655
656/* TDLS capabilities params */
657#define PARAM_MAX_TDLS_SESSION \
658 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
659#define PARAM_TDLS_FEATURE_SUPPORT \
660 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
661
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530662/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
664 * @wiphy: WIPHY structure pointer
665 * @wdev: Wireless device structure pointer
666 * @data: Pointer to the data received
667 * @data_len: Length of the data received
668 *
669 * This function provides TDLS capabilities
670 *
671 * Return: 0 on success and errno on failure
672 */
673static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
674 struct wireless_dev *wdev,
675 const void *data,
676 int data_len)
677{
678 int status;
679 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
680 struct sk_buff *skb;
681 uint32_t set = 0;
682
Jeff Johnson1f61b612016-02-12 16:28:33 -0800683 ENTER_DEV(wdev->netdev);
684
Anurag Chouhan6d760662016-02-20 16:05:43 +0530685 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 hdd_err("Command not allowed in FTM mode");
687 return -EPERM;
688 }
689
690 status = wlan_hdd_validate_context(hdd_ctx);
691 if (status)
692 return status;
693
694 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
695 NLMSG_HDRLEN);
696 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700697 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 goto fail;
699 }
700
701 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800702 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
704 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700705 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706 goto fail;
707 }
708 } else {
709 set = set | WIFI_TDLS_SUPPORT;
710 set = set | (hdd_ctx->config->fTDLSExternalControl ?
711 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
712 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
713 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800714 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
716 hdd_ctx->max_num_tdls_sta) ||
717 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
718 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700719 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800720 goto fail;
721 }
722 }
723 return cfg80211_vendor_cmd_reply(skb);
724fail:
725 if (skb)
726 kfree_skb(skb);
727 return -EINVAL;
728}
729
730/**
731 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
732 * @wiphy: WIPHY structure pointer
733 * @wdev: Wireless device structure pointer
734 * @data: Pointer to the data received
735 * @data_len: Length of the data received
736 *
737 * This function provides TDLS capabilities
738 *
739 * Return: 0 on success and errno on failure
740 */
741static int
742wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
743 struct wireless_dev *wdev,
744 const void *data,
745 int data_len)
746{
747 int ret;
748
749 cds_ssr_protect(__func__);
750 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
751 data, data_len);
752 cds_ssr_unprotect(__func__);
753
754 return ret;
755}
756#endif
757
758#ifdef QCA_HT_2040_COEX
759static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
760#endif
761
762#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
763/*
764 * FUNCTION: wlan_hdd_send_avoid_freq_event
765 * This is called when wlan driver needs to send vendor specific
766 * avoid frequency range event to userspace
767 */
768int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
769 tHddAvoidFreqList *pAvoidFreqList)
770{
771 struct sk_buff *vendor_event;
772
773 ENTER();
774
775 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700776 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777 return -EINVAL;
778 }
779
780 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700781 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782 return -EINVAL;
783 }
784
785 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
786 NULL,
787 sizeof(tHddAvoidFreqList),
788 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
789 GFP_KERNEL);
790 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700791 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792 return -EINVAL;
793 }
794
795 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
796 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
797
798 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
799
800 EXIT();
801 return 0;
802}
803#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
804
805/* vendor specific events */
806static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
807#ifdef FEATURE_WLAN_CH_AVOID
808 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
809 .vendor_id =
810 QCA_NL80211_VENDOR_ID,
811 .subcmd =
812 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
813 },
814#endif /* FEATURE_WLAN_CH_AVOID */
815
816#ifdef WLAN_FEATURE_NAN
817 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
818 .vendor_id =
819 QCA_NL80211_VENDOR_ID,
820 .subcmd =
821 QCA_NL80211_VENDOR_SUBCMD_NAN
822 },
823#endif
824
825#ifdef WLAN_FEATURE_STATS_EXT
826 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
827 .vendor_id =
828 QCA_NL80211_VENDOR_ID,
829 .subcmd =
830 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
831 },
832#endif /* WLAN_FEATURE_STATS_EXT */
833#ifdef FEATURE_WLAN_EXTSCAN
834 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
835 .vendor_id =
836 QCA_NL80211_VENDOR_ID,
837 .subcmd =
838 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
839 },
840 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
841 .vendor_id =
842 QCA_NL80211_VENDOR_ID,
843 .subcmd =
844 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
845 },
846 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
847 .
848 vendor_id
849 =
850 QCA_NL80211_VENDOR_ID,
851 .subcmd =
852 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
853 },
854 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
855 .
856 vendor_id
857 =
858 QCA_NL80211_VENDOR_ID,
859 .
860 subcmd =
861 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
862 },
863 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
864 .
865 vendor_id
866 =
867 QCA_NL80211_VENDOR_ID,
868 .
869 subcmd
870 =
871 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
872 },
873 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
874 .
875 vendor_id
876 =
877 QCA_NL80211_VENDOR_ID,
878 .subcmd =
879 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
880 },
881 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
882 .vendor_id =
883 QCA_NL80211_VENDOR_ID,
884 .subcmd =
885 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
886 },
887 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
888 .
889 vendor_id
890 =
891 QCA_NL80211_VENDOR_ID,
892 .subcmd =
893 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
894 },
895 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
896 .
897 vendor_id
898 =
899 QCA_NL80211_VENDOR_ID,
900 .subcmd =
901 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
902 },
903 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
904 .
905 vendor_id
906 =
907 QCA_NL80211_VENDOR_ID,
908 .
909 subcmd
910 =
911 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
912 },
913 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
914 .
915 vendor_id
916 =
917 QCA_NL80211_VENDOR_ID,
918 .
919 subcmd =
920 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
921 },
922 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
923 .
924 vendor_id
925 =
926 QCA_NL80211_VENDOR_ID,
927 .
928 subcmd
929 =
930 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
931 },
932 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
933 .
934 vendor_id
935 =
936 QCA_NL80211_VENDOR_ID,
937 .
938 subcmd
939 =
940 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
941 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942#endif /* FEATURE_WLAN_EXTSCAN */
943
944#ifdef WLAN_FEATURE_LINK_LAYER_STATS
945 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
946 .vendor_id =
947 QCA_NL80211_VENDOR_ID,
948 .subcmd =
949 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
950 },
951 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
952 .vendor_id =
953 QCA_NL80211_VENDOR_ID,
954 .subcmd =
955 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
956 },
957 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
958 .vendor_id =
959 QCA_NL80211_VENDOR_ID,
960 .subcmd =
961 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
962 },
963 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
964 .vendor_id =
965 QCA_NL80211_VENDOR_ID,
966 .subcmd =
967 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
968 },
969 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
970 .vendor_id =
971 QCA_NL80211_VENDOR_ID,
972 .subcmd =
973 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
974 },
975 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
976 .vendor_id =
977 QCA_NL80211_VENDOR_ID,
978 .subcmd =
979 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
980 },
Zhang Qianca38fb12016-12-23 11:10:48 +0800981 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
982 .vendor_id =
983 QCA_NL80211_VENDOR_ID,
984 .subcmd =
985 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
986 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800987#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
988 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
989 .vendor_id =
990 QCA_NL80211_VENDOR_ID,
991 .subcmd =
992 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
993 },
994 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
995 .vendor_id = QCA_NL80211_VENDOR_ID,
996 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
997 },
998#ifdef WLAN_FEATURE_ROAM_OFFLOAD
999 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1000 .vendor_id =
1001 QCA_NL80211_VENDOR_ID,
1002 .subcmd =
1003 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1004 },
1005#endif
1006 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1007 .vendor_id =
1008 QCA_NL80211_VENDOR_ID,
1009 .subcmd =
1010 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1011 },
1012 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1013 .vendor_id =
1014 QCA_NL80211_VENDOR_ID,
1015 .subcmd =
1016 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1017 },
1018 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1019 .vendor_id =
1020 QCA_NL80211_VENDOR_ID,
1021 .subcmd =
1022 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1023 },
1024 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1025 .vendor_id =
1026 QCA_NL80211_VENDOR_ID,
1027 .subcmd =
1028 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1029 },
1030 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1031 .vendor_id =
1032 QCA_NL80211_VENDOR_ID,
1033 .subcmd =
1034 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1035 },
1036#ifdef FEATURE_WLAN_EXTSCAN
1037 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1038 .vendor_id = QCA_NL80211_VENDOR_ID,
1039 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1040 },
1041 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1042 .vendor_id = QCA_NL80211_VENDOR_ID,
1043 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1044 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001045 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1046 .vendor_id = QCA_NL80211_VENDOR_ID,
1047 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1048 },
1049#endif /* FEATURE_WLAN_EXTSCAN */
1050 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1053 },
1054#ifdef WLAN_FEATURE_MEMDUMP
1055 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1058 },
1059#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001060#ifdef WLAN_FEATURE_TSF
1061 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1062 .vendor_id = QCA_NL80211_VENDOR_ID,
1063 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1064 },
1065#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1069 },
1070 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1071 .vendor_id = QCA_NL80211_VENDOR_ID,
1072 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1073 },
1074 /* OCB events */
1075 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1078 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001079#ifdef FEATURE_LFR_SUBNET_DETECTION
1080 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1083 },
1084#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001085
1086#ifdef WLAN_FEATURE_NAN_DATAPATH
1087 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1088 .vendor_id = QCA_NL80211_VENDOR_ID,
1089 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1090 },
1091#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001092
1093 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1094 .vendor_id = QCA_NL80211_VENDOR_ID,
1095 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1096 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301097 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1098 .vendor_id = QCA_NL80211_VENDOR_ID,
1099 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1100 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301101 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1102 .vendor_id = QCA_NL80211_VENDOR_ID,
1103 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1104 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001105#ifdef WLAN_UMAC_CONVERGENCE
1106 COMMON_VENDOR_EVENTS
1107#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108};
1109
1110/**
1111 * __is_driver_dfs_capable() - get driver DFS capability
1112 * @wiphy: pointer to wireless wiphy structure.
1113 * @wdev: pointer to wireless_dev structure.
1114 * @data: Pointer to the data to be passed via vendor interface
1115 * @data_len:Length of the data to be passed
1116 *
1117 * This function is called by userspace to indicate whether or not
1118 * the driver supports DFS offload.
1119 *
1120 * Return: 0 on success, negative errno on failure
1121 */
1122static int __is_driver_dfs_capable(struct wiphy *wiphy,
1123 struct wireless_dev *wdev,
1124 const void *data,
1125 int data_len)
1126{
1127 u32 dfs_capability = 0;
1128 struct sk_buff *temp_skbuff;
1129 int ret_val;
1130 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1131
Jeff Johnson1f61b612016-02-12 16:28:33 -08001132 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001133
1134 ret_val = wlan_hdd_validate_context(hdd_ctx);
1135 if (ret_val)
1136 return ret_val;
1137
Anurag Chouhan6d760662016-02-20 16:05:43 +05301138 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001139 hdd_err("Command not allowed in FTM mode");
1140 return -EPERM;
1141 }
1142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001143 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144
1145 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1146 NLMSG_HDRLEN);
1147
1148 if (temp_skbuff != NULL) {
1149 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1150 dfs_capability);
1151 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001152 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001153 kfree_skb(temp_skbuff);
1154
1155 return ret_val;
1156 }
1157
1158 return cfg80211_vendor_cmd_reply(temp_skbuff);
1159 }
1160
Jeff Johnson020db452016-06-29 14:37:26 -07001161 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001162 return -ENOMEM;
1163}
1164
1165/**
1166 * is_driver_dfs_capable() - get driver DFS capability
1167 * @wiphy: pointer to wireless wiphy structure.
1168 * @wdev: pointer to wireless_dev structure.
1169 * @data: Pointer to the data to be passed via vendor interface
1170 * @data_len:Length of the data to be passed
1171 *
1172 * This function is called by userspace to indicate whether or not
1173 * the driver supports DFS offload. This is an SSR-protected
1174 * wrapper function.
1175 *
1176 * Return: 0 on success, negative errno on failure
1177 */
1178static int is_driver_dfs_capable(struct wiphy *wiphy,
1179 struct wireless_dev *wdev,
1180 const void *data,
1181 int data_len)
1182{
1183 int ret;
1184
1185 cds_ssr_protect(__func__);
1186 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1187 cds_ssr_unprotect(__func__);
1188
1189 return ret;
1190}
1191
1192/**
1193 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1194 *
1195 * @adapter: SAP adapter pointer
1196 *
1197 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1198 * radio. So in case of DFS MCC scenario override current SAP given config
1199 * to follow concurrent SAP DFS config
1200 *
1201 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1202 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001203int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1204{
1205 hdd_adapter_t *con_sap_adapter;
1206 tsap_Config_t *sap_config, *con_sap_config;
1207 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001208 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001209
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001210 if (!hdd_ctx) {
1211 hdd_err("hdd context is NULL");
1212 return 0;
1213 }
1214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215 /*
1216 * Check if AP+AP case, once primary AP chooses a DFS
1217 * channel secondary AP should always follow primary APs channel
1218 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001219 if (!policy_mgr_concurrent_beaconing_sessions_running(
1220 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 return 0;
1222
1223 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1224 if (!con_sap_adapter)
1225 return 0;
1226
1227 sap_config = &adapter->sessionCtx.ap.sapConfig;
1228 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1229 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1230
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001231 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 return 0;
1233
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001234 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001235 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001236 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237 sap_config->channel = con_ch;
1238
1239 if (con_sap_config->acs_cfg.acs_mode == true) {
1240 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1241 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001242 hdd_err("Primary AP channel config error");
1243 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001244 con_ch, con_sap_config->acs_cfg.pri_ch,
1245 con_sap_config->acs_cfg.ht_sec_ch);
1246 return -EINVAL;
1247 }
1248 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1249 * MCC restriction. So free ch list allocated in do_acs
1250 * func for Sec AP and realloc for Pri AP ch list size
1251 */
1252 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301253 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001254
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301255 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001256 &con_sap_config->acs_cfg,
1257 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301258 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 sizeof(uint8_t) *
1260 con_sap_config->acs_cfg.ch_list_count);
1261 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001262 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263 return -ENOMEM;
1264 }
1265
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301266 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001267 con_sap_config->acs_cfg.ch_list,
1268 con_sap_config->acs_cfg.ch_list_count);
1269
1270 } else {
1271 sap_config->acs_cfg.pri_ch = con_ch;
1272 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1273 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1274 }
1275
1276 return con_ch;
1277}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001278
1279/**
1280 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1281 * @sap_cfg: pointer to SAP config struct
1282 *
1283 * This function sets the default ACS start and end channel for the given band
1284 * and also parses the given ACS channel list.
1285 *
1286 * Return: None
1287 */
1288
1289static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1290 bool vht_enabled)
1291{
1292 int i;
1293 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001295 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1296 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001299 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1300 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1302 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001303 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1304 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1306 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001307 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1308 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001309 }
1310
1311 if (ht_enabled)
1312 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1313
1314 if (vht_enabled)
1315 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1316
1317
1318 /* Parse ACS Chan list from hostapd */
1319 if (!sap_cfg->acs_cfg.ch_list)
1320 return;
1321
1322 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1323 sap_cfg->acs_cfg.end_ch =
1324 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1325 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301326 /* avoid channel as start channel */
1327 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1328 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001329 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1330 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1331 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1332 }
1333}
1334
1335
1336static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1337
1338/**
1339 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1340 * @adapter: pointer to SAP adapter struct
1341 *
1342 * This function starts the ACS procedure if there are no
1343 * constraints like MBSSID DFS restrictions.
1344 *
1345 * Return: Status of ACS Start procedure
1346 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301347int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001348{
1349
1350 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1351 tsap_Config_t *sap_config;
1352 tpWLAN_SAPEventCB acs_event_callback;
1353 int status;
1354
1355 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301356 if (hdd_ctx->acs_policy.acs_channel)
1357 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1358 else
1359 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001360
1361 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001362 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001363 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001364
1365 if (status > 0) {
1366 /*notify hostapd about channel override */
1367 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1368 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1369 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 }
Jeff Johnson68755312017-02-10 11:46:55 -08001371
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1373 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001374 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375 return -EINVAL;
1376 }
1377
1378 acs_event_callback = hdd_hostapd_sap_event_cb;
1379
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301380 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301381 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301382 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 acs_event_callback, sap_config, adapter->dev);
1386
1387
1388 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001389 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 return -EINVAL;
1391 }
bings394afdd2017-01-09 11:22:38 +08001392 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1393 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1395
1396 return 0;
1397}
1398
1399/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301400 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1401 * @ap_adapter: AP adapter
1402 * @nol: Non-occupancy list
1403 * @nol_len: Length of NOL
1404 *
1405 * Get the NOL for SAP
1406 *
1407 * Return: Zero on success, non-zero on failure
1408 */
1409static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1410 uint32_t *nol_len)
1411{
1412 QDF_STATUS ret;
1413
1414 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1415 nol, nol_len);
1416 if (QDF_IS_STATUS_ERROR(ret))
1417 return -EINVAL;
1418
1419 return 0;
1420}
1421
1422/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301423 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1424 * @hdd_ctx: hdd context
1425 * @acs_chan_params: external acs channel params
1426 * @sap_config: SAP config
1427 *
1428 * This API provides unsorted pcl list.
1429 * this list is a subset of the valid channel list given by hostapd.
1430 * if channel is not present in pcl, weightage will be given as zero
1431 *
1432 * Return: Zero on success, non-zero on failure
1433 */
1434static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1435 struct hdd_vendor_acs_chan_params *acs_chan_params,
1436 tsap_Config_t *sap_config)
1437{
1438 int i, j;
1439
1440 for (i = 0; i < acs_chan_params->channel_count; i++) {
1441 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1442 if (acs_chan_params->channel_list[i] ==
1443 sap_config->acs_cfg.pcl_channels[j]) {
1444 acs_chan_params->vendor_pcl_list[i] =
1445 sap_config->acs_cfg.pcl_channels[j];
1446 acs_chan_params->vendor_weight_list[i] =
1447 sap_config->acs_cfg.
1448 pcl_channels_weight_list[j];
1449 break;
1450 } else {
1451 acs_chan_params->vendor_pcl_list[i] =
1452 acs_chan_params->channel_list[i];
1453 acs_chan_params->vendor_weight_list[i] = 0;
1454 }
1455 }
1456 }
1457 if (hdd_ctx->unsafe_channel_count == 0)
1458 return;
1459 /* Update unsafe channel weight as zero */
1460 for (i = 0; i < acs_chan_params->channel_count; i++) {
1461 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1462 if (acs_chan_params->channel_list[i] ==
1463 hdd_ctx->unsafe_channel_list[j]) {
1464 acs_chan_params->vendor_weight_list[i] = 0;
1465 }
1466 }
1467 }
1468}
1469
1470/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301471 * hdd_update_reg_chan_info : This API contructs channel info
1472 * for all the given channel
1473 * @adapter: pointer to SAP adapter struct
1474 * @channel_count: channel count
1475 * @channel_list: channel list
1476 *
1477 * Return: Status of of channel information updation
1478 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301479static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301480 uint32_t channel_count,
1481 uint8_t *channel_list)
1482{
1483 int i;
1484 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001485 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301486 uint8_t bw_offset = 0, chan = 0;
1487 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1488 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1489
1490 /* memory allocation */
1491 sap_config->channel_info = qdf_mem_malloc(
1492 sizeof(struct hdd_channel_info) *
1493 channel_count);
1494 if (!sap_config->channel_info) {
1495 hdd_err("memory allocation failed");
1496 return -ENOMEM;
1497
1498 }
1499 for (i = 0; i < channel_count; i++) {
1500 icv = &sap_config->channel_info[i];
1501 chan = channel_list[i];
1502
1503 if (chan == 0)
1504 continue;
1505
1506 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1507 bw_offset = 1 << BW_40_OFFSET_BIT;
1508 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1509 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001510 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301511 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001512 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1513 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301514
1515 /* filling demo values */
1516 icv->max_radio_power = HDD_MAX_TX_POWER;
1517 icv->min_radio_power = HDD_MIN_TX_POWER;
1518 /* not supported in current driver */
1519 icv->max_antenna_gain = 0;
1520
1521 icv->reg_class_id = wlan_hdd_find_opclass(
1522 WLAN_HDD_GET_HAL_CTX(adapter),
1523 chan, bw_offset);
1524
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001525 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301526 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001527 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1528 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301529 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1530 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1531 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001532
Kapil Gupta086c6202016-12-11 18:17:06 +05301533 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001534 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301535 sap_config->acs_cfg.ch_width,
1536 sap_config->acs_cfg.is_ht_enabled,
1537 sap_config->acs_cfg.is_vht_enabled,
1538 hdd_ctx->config->enable_sub_20_channel_width);
1539
1540 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1541 icv->freq, icv->flags,
1542 icv->flagext, icv->ieee_chan_number,
1543 icv->max_reg_power, icv->max_radio_power,
1544 icv->min_radio_power, icv->reg_class_id,
1545 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1546 icv->vht_center_freq_seg1);
1547 }
1548 return 0;
1549}
1550
1551/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1552#define CHAN_INFO_ATTR_FLAGS \
1553 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1554#define CHAN_INFO_ATTR_FLAG_EXT \
1555 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1556#define CHAN_INFO_ATTR_FREQ \
1557 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1558#define CHAN_INFO_ATTR_MAX_REG_POWER \
1559 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1560#define CHAN_INFO_ATTR_MAX_POWER \
1561 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1562#define CHAN_INFO_ATTR_MIN_POWER \
1563 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1564#define CHAN_INFO_ATTR_REG_CLASS_ID \
1565 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1566#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1567 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1568#define CHAN_INFO_ATTR_VHT_SEG_0 \
1569 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1570#define CHAN_INFO_ATTR_VHT_SEG_1 \
1571 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1572
1573/**
1574 * hdd_cfg80211_update_channel_info() - add channel info attributes
1575 * @skb: pointer to sk buff
1576 * @hdd_ctx: pointer to hdd station context
1577 * @idx: attribute index
1578 *
1579 * Return: Success(0) or reason code for failure
1580 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301581static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301582hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1583 tsap_Config_t *sap_config, int idx)
1584{
1585 struct nlattr *nla_attr, *channel;
1586 struct hdd_channel_info *icv;
1587 int i;
1588
1589 nla_attr = nla_nest_start(skb, idx);
1590 if (!nla_attr)
1591 goto fail;
1592
1593 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1594 channel = nla_nest_start(skb, i);
1595 if (!channel)
1596 goto fail;
1597
1598 icv = &sap_config->channel_info[i];
1599 if (!icv) {
1600 hdd_err("channel info not found");
1601 goto fail;
1602 }
1603 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1604 icv->freq) ||
1605 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1606 icv->flags) ||
1607 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1608 icv->flagext) ||
1609 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1610 icv->max_reg_power) ||
1611 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1612 icv->max_radio_power) ||
1613 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1614 icv->min_radio_power) ||
1615 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1616 icv->reg_class_id) ||
1617 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1618 icv->max_antenna_gain) ||
1619 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1620 icv->vht_center_freq_seg0) ||
1621 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1622 icv->vht_center_freq_seg1)) {
1623 hdd_err("put fail");
1624 goto fail;
1625 }
1626 nla_nest_end(skb, channel);
1627 }
1628 nla_nest_end(skb, nla_attr);
1629 return 0;
1630fail:
1631 hdd_err("nl channel update failed");
1632 return -EINVAL;
1633}
1634#undef CHAN_INFO_ATTR_FLAGS
1635#undef CHAN_INFO_ATTR_FLAG_EXT
1636#undef CHAN_INFO_ATTR_FREQ
1637#undef CHAN_INFO_ATTR_MAX_REG_POWER
1638#undef CHAN_INFO_ATTR_MAX_POWER
1639#undef CHAN_INFO_ATTR_MIN_POWER
1640#undef CHAN_INFO_ATTR_REG_CLASS_ID
1641#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1642#undef CHAN_INFO_ATTR_VHT_SEG_0
1643#undef CHAN_INFO_ATTR_VHT_SEG_1
1644
1645/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301646 * hdd_cfg80211_update_pcl() - add pcl info attributes
1647 * @skb: pointer to sk buff
1648 * @hdd_ctx: pointer to hdd station context
1649 * @idx: attribute index
1650 * @vendor_pcl_list: PCL list
1651 * @vendor_weight_list: PCL weights
1652 *
1653 * Return: Success(0) or reason code for failure
1654 */
1655static int32_t
1656hdd_cfg80211_update_pcl(struct sk_buff *skb,
1657 uint8_t ch_list_count, int idx,
1658 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1659{
1660 struct nlattr *nla_attr, *channel;
1661 int i;
1662
1663 nla_attr = nla_nest_start(skb, idx);
1664
1665 if (!nla_attr)
1666 goto fail;
1667
1668 for (i = 0; i < ch_list_count; i++) {
1669 channel = nla_nest_start(skb, i);
1670 if (!channel)
1671 goto fail;
1672 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1673 vendor_pcl_list[i]) ||
1674 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1675 vendor_weight_list[i])) {
1676 hdd_err("put fail");
1677 goto fail;
1678 }
1679 nla_nest_end(skb, channel);
1680 }
1681 nla_nest_end(skb, nla_attr);
1682
1683 return 0;
1684fail:
1685 hdd_err("updating pcl list failed");
1686 return -EINVAL;
1687}
1688
1689static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1690{
1691 /* Get scan band */
1692 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1693 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1694 *band = eCSR_BAND_24;
1695 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1696 *band = eCSR_BAND_5G;
1697 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1698 *band = eCSR_BAND_ALL;
1699 }
1700 /* Auto is not supported currently */
1701 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1702 hdd_err("invalid band");
1703 *band = eCSR_BAND_24;
1704 }
1705}
1706
1707void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1708 uint8_t reason)
1709{
1710 struct sk_buff *skb;
1711 tsap_Config_t *sap_config;
1712 uint32_t channel_count = 0, status;
1713 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1714 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1715 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1716 struct hdd_vendor_acs_chan_params acs_chan_params;
1717 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1718 eCsrBand band = eCSR_BAND_24;
1719 eCsrPhyMode phy_mode;
1720
1721 if (!hdd_ctx) {
1722 hdd_err("HDD context is NULL");
1723 return;
1724 }
1725
1726 ENTER();
1727 sap_config = &adapter->sessionCtx.ap.sapConfig;
1728
1729 /* Get valid channels for SAP */
1730 wlan_hdd_sap_get_valid_channellist(adapter,
1731 &channel_count, channel_list);
1732
1733 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1734 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1735 /* Get phymode */
1736 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1737
1738 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1739 &(adapter->wdev),
1740 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1741 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1742 GFP_KERNEL);
1743
1744 if (!skb) {
1745 hdd_err("cfg80211_vendor_event_alloc failed");
1746 return;
1747 }
1748 /*
1749 * Application expects pcl to be a subset of channel list
1750 * Remove all channels which are not in channel list from pcl
1751 * and add weight as zero
1752 */
1753 acs_chan_params.channel_count = channel_count;
1754 acs_chan_params.channel_list = channel_list;
1755 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1756 acs_chan_params.vendor_weight_list = vendor_weight_list;
1757
1758 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1759 sap_config);
1760 /* Update values in NL buffer */
1761 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1762 reason) ||
1763 nla_put_u8(skb,
1764 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1765 false) ||
1766 nla_put_u8(skb,
1767 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1768 true) ||
1769 nla_put_u8(skb,
1770 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1771 true) ||
1772 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1773 sap_config->acs_cfg.ch_width) ||
1774 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1775 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1776 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1777 band) ||
1778 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1779 phy_mode) ||
1780 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1781 channel_count, channel_list)) {
1782 hdd_err("nla put fail");
1783 goto fail;
1784 }
1785 status = hdd_cfg80211_update_pcl(skb, channel_count,
1786 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1787 vendor_pcl_list, vendor_weight_list);
1788
1789 if (status != 0)
1790 goto fail;
1791
1792 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1793 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1794
1795 if (status != 0)
1796 goto fail;
1797
1798 cfg80211_vendor_event(skb, GFP_KERNEL);
1799 return;
1800fail:
1801 if (skb)
1802 kfree_skb(skb);
1803}
1804
1805static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1806{
1807 struct hdd_external_acs_timer_context *timer_context;
1808
1809 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1810 return 0;
1811
1812 hdd_notice("Starting vendor app based ACS");
1813 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1814 timer_context->adapter = adapter;
1815
1816 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1817 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1818 QDF_TIMER_TYPE_SW,
1819 hdd_acs_response_timeout_handler, timer_context);
1820 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1821 return 0;
1822}
1823
1824/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001825 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1826 * @wiphy: Linux wiphy struct pointer
1827 * @wdev: Linux wireless device struct pointer
1828 * @data: ACS information from hostapd
1829 * @data_len: ACS information length
1830 *
1831 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1832 * and starts ACS procedure.
1833 *
1834 * Return: ACS procedure start status
1835 */
1836
1837static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1838 struct wireless_dev *wdev,
1839 const void *data, int data_len)
1840{
1841 struct net_device *ndev = wdev->netdev;
1842 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1843 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1844 tsap_Config_t *sap_config;
1845 struct sk_buff *temp_skbuff;
1846 int status = -EINVAL, i = 0;
1847 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1848 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301849 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001850
1851 /* ***Note*** Donot set SME config related to ACS operation here because
1852 * ACS operation is not synchronouse and ACS for Second AP may come when
1853 * ACS operation for first AP is going on. So only do_acs is split to
1854 * seperate start_acs routine. Also SME-PMAC struct that is used to
1855 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1856 * config shall be set only from start_acs.
1857 */
1858
1859 /* nla_policy Policy template. Policy not applied as some attributes are
1860 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1861 *
1862 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1863 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1864 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1865 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1866 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1867 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1868 */
1869
Jeff Johnson1f61b612016-02-12 16:28:33 -08001870 ENTER_DEV(ndev);
1871
Anurag Chouhan6d760662016-02-20 16:05:43 +05301872 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001873 hdd_err("Command not allowed in FTM mode");
1874 return -EPERM;
1875 }
1876
Kapil Gupta8878ad92017-02-13 11:56:04 +05301877 if (hdd_ctx->config->force_sap_acs &&
1878 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001879 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880 return -EPERM;
1881 }
1882
1883 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301884 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301886
Naveen Rawat64e477e2016-05-20 10:34:56 -07001887 if (cds_is_sub_20_mhz_enabled()) {
1888 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1889 status = -EINVAL;
1890 goto out;
1891 }
1892
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001893 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301894 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001895
1896 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1897 NULL);
1898 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001899 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001900 goto out;
1901 }
1902
1903 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001904 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 goto out;
1906 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301907 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1908 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909
1910 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1911 ht_enabled =
1912 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1913 else
1914 ht_enabled = 0;
1915
1916 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1917 ht40_enabled =
1918 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1919 else
1920 ht40_enabled = 0;
1921
1922 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1923 vht_enabled =
1924 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1925 else
1926 vht_enabled = 0;
1927
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301928 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1929 vht_enabled = 0;
1930 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1931 }
1932
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1934 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1935 } else {
1936 if (ht_enabled && ht40_enabled)
1937 ch_width = 40;
1938 else
1939 ch_width = 20;
1940 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301941
1942 /* this may be possible, when sap_force_11n_for_11ac is set */
1943 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1944 if (ht_enabled && ht40_enabled)
1945 ch_width = 40;
1946 else
1947 ch_width = 20;
1948 }
1949
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001950 if (ch_width == 80)
1951 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1952 else if (ch_width == 40)
1953 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1954 else
1955 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1956
1957 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1958 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1959 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1960 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1961 * since it contains the frequency values of the channels in
1962 * the channel list.
1963 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1964 * is present
1965 */
1966 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1967 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1968 sap_config->acs_cfg.ch_list_count = nla_len(
1969 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1970 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301971 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 sizeof(uint8_t) *
1973 sap_config->acs_cfg.ch_list_count);
1974 if (sap_config->acs_cfg.ch_list == NULL)
1975 goto out;
1976
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301977 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 sap_config->acs_cfg.ch_list_count);
1979 }
1980 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1981 uint32_t *freq =
1982 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1983 sap_config->acs_cfg.ch_list_count = nla_len(
1984 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1985 sizeof(uint32_t);
1986 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301987 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 sap_config->acs_cfg.ch_list_count);
1989 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001990 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991 status = -ENOMEM;
1992 goto out;
1993 }
1994
1995 /* convert frequency to channel */
1996 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1997 sap_config->acs_cfg.ch_list[i] =
1998 ieee80211_frequency_to_channel(freq[i]);
1999 }
2000 }
2001
2002 hdd_debug("get pcl for DO_ACS vendor command");
2003
2004 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002005 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302006 sap_config->acs_cfg.pcl_channels,
2007 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302008 sap_config->acs_cfg.pcl_channels_weight_list,
2009 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302010 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002011 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302014 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2015 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002016 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 vht_enabled = 1;
2018 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2019 sap_config->acs_cfg.ch_width =
2020 hdd_ctx->config->vhtChannelWidth;
2021 /* No VHT80 in 2.4G so perform ACS accordingly */
2022 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302023 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002024 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302025 ch_width = 40;
2026 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002027 }
2028
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302029 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2030
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002031 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 -08002032 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2033 ch_width, ht_enabled, vht_enabled,
2034 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2035
Kapil Gupta8878ad92017-02-13 11:56:04 +05302036 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2037 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2038
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002039 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002040 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041 sap_config->acs_cfg.ch_list_count);
2042 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002043 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002044 }
2045 sap_config->acs_cfg.acs_mode = true;
2046 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002047 /* ***Note*** Completion variable usage is not allowed
2048 * here since ACS scan operation may take max 2.2 sec
2049 * for 5G band:
2050 * 9 Active channel X 40 ms active scan time +
2051 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2053 * for this long. So we split up the scanning part.
2054 */
2055 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002056 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002057 status = 0;
2058 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302059 /* Check if vendor specific acs is enabled */
2060 if (hdd_ctx->config->vendor_acs_support) {
2061 sap_config->acs_cfg.hw_mode = hw_mode;
2062 hdd_create_acs_timer(adapter);
2063 hdd_update_acs_timer_reason(adapter,
2064 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2065 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2066 wlan_sap_set_vendor_acs(
2067 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2068 true);
2069 else
2070 wlan_sap_set_vendor_acs(
2071 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2072 false);
2073
2074 } else
2075 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002076 }
2077
2078out:
2079 if (0 == status) {
2080 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2081 NLMSG_HDRLEN);
2082 if (temp_skbuff != NULL)
2083 return cfg80211_vendor_cmd_reply(temp_skbuff);
2084 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002085 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002086 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2087
2088 return status;
2089}
2090
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002091/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002092 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2093 * @wiphy: Linux wiphy struct pointer
2094 * @wdev: Linux wireless device struct pointer
2095 * @data: ACS information from hostapd
2096 * @data_len: ACS information len
2097 *
2098 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2099 * and starts ACS procedure.
2100 *
2101 * Return: ACS procedure start status
2102 */
2103
2104static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2105 struct wireless_dev *wdev,
2106 const void *data, int data_len)
2107{
2108 int ret;
2109
2110 cds_ssr_protect(__func__);
2111 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2112 cds_ssr_unprotect(__func__);
2113
2114 return ret;
2115}
2116
2117/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002118 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2119 * @adapter: Pointer to adapter struct
2120 *
2121 * This function handle cleanup of what was done in DO_ACS, including free
2122 * memory.
2123 *
2124 * Return: void
2125 */
2126
2127void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2128{
2129 if (adapter == NULL)
2130 return;
2131 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2132 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2133 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2134 }
2135}
2136
2137/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002138 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2139 * @work: Linux workqueue struct pointer for ACS work
2140 *
2141 * This function starts the ACS procedure which was marked pending when an ACS
2142 * procedure was in progress for a concurrent SAP interface.
2143 *
2144 * Return: None
2145 */
2146
2147static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2148{
2149 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2150 acs_pending_work.work);
2151 wlan_hdd_cfg80211_start_acs(adapter);
2152}
2153
2154/**
2155 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2156 * @adapter: Pointer to SAP adapter struct
2157 * @pri_channel: SAP ACS procedure selected Primary channel
2158 * @sec_channel: SAP ACS procedure selected secondary channel
2159 *
2160 * This is a callback function from SAP module on ACS procedure is completed.
2161 * This function send the ACS selected channel information to hostapd
2162 *
2163 * Return: None
2164 */
2165
2166void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2167{
2168 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2169 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2170 struct sk_buff *vendor_event;
2171 int ret_val;
2172 hdd_adapter_t *con_sap_adapter;
2173 uint16_t ch_width;
2174
2175 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002176 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002177 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2178 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2179 GFP_KERNEL);
2180
2181 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002182 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 return;
2184 }
2185
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186 ret_val = nla_put_u8(vendor_event,
2187 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2188 sap_cfg->acs_cfg.pri_ch);
2189 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002190 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 kfree_skb(vendor_event);
2192 return;
2193 }
2194
2195 ret_val = nla_put_u8(vendor_event,
2196 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2197 sap_cfg->acs_cfg.ht_sec_ch);
2198 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002199 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002200 kfree_skb(vendor_event);
2201 return;
2202 }
2203
2204 ret_val = nla_put_u8(vendor_event,
2205 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2206 sap_cfg->acs_cfg.vht_seg0_center_ch);
2207 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002208 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002209 kfree_skb(vendor_event);
2210 return;
2211 }
2212
2213 ret_val = nla_put_u8(vendor_event,
2214 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2215 sap_cfg->acs_cfg.vht_seg1_center_ch);
2216 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002217 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218 kfree_skb(vendor_event);
2219 return;
2220 }
2221
2222 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2223 ch_width = 80;
2224 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2225 ch_width = 40;
2226 else
2227 ch_width = 20;
2228
2229 ret_val = nla_put_u16(vendor_event,
2230 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2231 ch_width);
2232 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002233 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234 kfree_skb(vendor_event);
2235 return;
2236 }
2237 if (sap_cfg->acs_cfg.pri_ch > 14)
2238 ret_val = nla_put_u8(vendor_event,
2239 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2240 QCA_ACS_MODE_IEEE80211A);
2241 else
2242 ret_val = nla_put_u8(vendor_event,
2243 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2244 QCA_ACS_MODE_IEEE80211G);
2245
2246 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002247 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002248 kfree_skb(vendor_event);
2249 return;
2250 }
2251
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002252 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 -08002253 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2254 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2255 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2256
2257 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2258 /* ***Note*** As already mentioned Completion variable usage is not
2259 * allowed here since ACS scan operation may take max 2.2 sec.
2260 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2261 * operation.
2262 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2263 * when Primary AP ACS is complete and secondary AP ACS is started here
2264 * immediately, Primary AP start_bss may come inbetween ACS operation
2265 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2266 * delay. This path and below constraint will be removed on sessionizing
2267 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2268 * As per design constraint user space control application must take
2269 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2270 * this code path. Sec AP hostapd should be started after Primary AP
2271 * start beaconing which can be confirmed by getchannel iwpriv command
2272 */
2273
2274 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2275 if (con_sap_adapter &&
2276 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002277 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2278 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279 /* Lets give 500ms for OBSS + START_BSS to complete */
2280 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2281 msecs_to_jiffies(500));
2282 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2283 }
2284
2285 return;
2286}
2287
2288static int
2289__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2290 struct wireless_dev *wdev,
2291 const void *data,
2292 int data_len)
2293{
2294 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2295 struct sk_buff *skb = NULL;
2296 uint32_t fset = 0;
2297 int ret;
2298
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002299 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302300
Anurag Chouhan6d760662016-02-20 16:05:43 +05302301 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 hdd_err("Command not allowed in FTM mode");
2303 return -EPERM;
2304 }
2305
2306 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302307 if (ret)
2308 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309
2310 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002311 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 fset |= WIFI_FEATURE_INFRA;
2313 }
2314 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002315 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002316 fset |= WIFI_FEATURE_INFRA_5G;
2317 }
2318#ifdef WLAN_FEATURE_P2P
2319 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2320 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002321 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002322 fset |= WIFI_FEATURE_P2P;
2323 }
2324#endif
2325 fset |= WIFI_FEATURE_SOFT_AP;
2326
2327 /* HOTSPOT is a supplicant feature, enable it by default */
2328 fset |= WIFI_FEATURE_HOTSPOT;
2329
2330#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302331 if (pHddCtx->config->extscan_enabled &&
2332 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002333 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002334 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2335 }
2336#endif
2337 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002338 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002339 fset |= WIFI_FEATURE_NAN;
2340 }
2341 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002342 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 fset |= WIFI_FEATURE_D2D_RTT;
2344 fset |= WIFI_FEATURE_D2AP_RTT;
2345 }
2346#ifdef FEATURE_WLAN_SCAN_PNO
2347 if (pHddCtx->config->configPNOScanSupport &&
2348 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002349 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350 fset |= WIFI_FEATURE_PNO;
2351 }
2352#endif
2353 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2354#ifdef FEATURE_WLAN_TDLS
2355 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2356 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002357 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002358 fset |= WIFI_FEATURE_TDLS;
2359 }
2360 if (sme_is_feature_supported_by_fw(TDLS) &&
2361 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2362 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002363 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002364 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2365 }
2366#endif
2367#ifdef WLAN_AP_STA_CONCURRENCY
2368 fset |= WIFI_FEATURE_AP_STA;
2369#endif
2370 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002371 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372
2373 if (hdd_link_layer_stats_supported())
2374 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2375
2376 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2377 NLMSG_HDRLEN);
2378 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002379 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380 return -EINVAL;
2381 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002382 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002384 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002385 goto nla_put_failure;
2386 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302387 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302388 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002389nla_put_failure:
2390 kfree_skb(skb);
2391 return -EINVAL;
2392}
2393
2394/**
2395 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2396 * @wiphy: pointer to wireless wiphy structure.
2397 * @wdev: pointer to wireless_dev structure.
2398 * @data: Pointer to the data to be passed via vendor interface
2399 * @data_len:Length of the data to be passed
2400 *
2401 * Return: Return the Success or Failure code.
2402 */
2403static int
2404wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2405 struct wireless_dev *wdev,
2406 const void *data, int data_len)
2407{
2408 int ret = 0;
2409
2410 cds_ssr_protect(__func__);
2411 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2412 data, data_len);
2413 cds_ssr_unprotect(__func__);
2414
2415 return ret;
2416}
2417
2418/**
2419 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2420 * @wiphy: pointer to wireless wiphy structure.
2421 * @wdev: pointer to wireless_dev structure.
2422 * @data: Pointer to the data to be passed via vendor interface
2423 * @data_len:Length of the data to be passed
2424 *
2425 * Set the MAC address that is to be used for scanning.
2426 *
2427 * Return: Return the Success or Failure code.
2428 */
2429static int
2430__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2431 struct wireless_dev *wdev,
2432 const void *data,
2433 int data_len)
2434{
2435 tpSirScanMacOui pReqMsg = NULL;
2436 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2437 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302438 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 int ret;
2440
Jeff Johnson1f61b612016-02-12 16:28:33 -08002441 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442
Anurag Chouhan6d760662016-02-20 16:05:43 +05302443 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444 hdd_err("Command not allowed in FTM mode");
2445 return -EPERM;
2446 }
2447
2448 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302449 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451
2452 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002453 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 return -ENOTSUPP;
2455 }
2456
2457 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2458 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002459 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 return -EINVAL;
2461 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302462 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002464 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465 return -ENOMEM;
2466 }
2467 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002468 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 goto fail;
2470 }
2471 nla_memcpy(&pReqMsg->oui[0],
2472 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2473 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002474 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002475 pReqMsg->oui[1], pReqMsg->oui[2]);
2476 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302477 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002478 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 goto fail;
2480 }
2481 return 0;
2482fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302483 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484 return -EINVAL;
2485}
2486
2487/**
2488 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2489 * @wiphy: pointer to wireless wiphy structure.
2490 * @wdev: pointer to wireless_dev structure.
2491 * @data: Pointer to the data to be passed via vendor interface
2492 * @data_len:Length of the data to be passed
2493 *
2494 * Set the MAC address that is to be used for scanning. This is an
2495 * SSR-protecting wrapper function.
2496 *
2497 * Return: Return the Success or Failure code.
2498 */
2499static int
2500wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2501 struct wireless_dev *wdev,
2502 const void *data,
2503 int data_len)
2504{
2505 int ret;
2506
2507 cds_ssr_protect(__func__);
2508 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2509 data, data_len);
2510 cds_ssr_unprotect(__func__);
2511
2512 return ret;
2513}
2514
2515/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302516 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2517 * @wiphy: pointer phy adapter
2518 * @wdev: pointer to wireless device structure
2519 * @data: pointer to data buffer
2520 * @data_len: length of data
2521 *
2522 * This routine will give concurrency matrix
2523 *
2524 * Return: int status code
2525 */
2526static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2527 struct wireless_dev *wdev,
2528 const void *data,
2529 int data_len)
2530{
2531 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2532 uint8_t i, feature_sets, max_feature_sets;
2533 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2534 struct sk_buff *reply_skb;
2535 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2536 int ret;
2537
2538 ENTER_DEV(wdev->netdev);
2539
2540 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2541 hdd_err("Command not allowed in FTM mode");
2542 return -EPERM;
2543 }
2544
2545 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302546 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302547 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302548
2549 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2550 data, data_len, NULL)) {
2551 hdd_err("Invalid ATTR");
2552 return -EINVAL;
2553 }
2554
2555 /* Parse and fetch max feature set */
2556 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2557 hdd_err("Attr max feature set size failed");
2558 return -EINVAL;
2559 }
2560 max_feature_sets = nla_get_u32(tb[
2561 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002562 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302563
2564 /* Fill feature combination matrix */
2565 feature_sets = 0;
2566 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002567 WIFI_FEATURE_P2P;
2568 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2569 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302570 /* Add more feature combinations here */
2571
2572 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002573 hdd_debug("Number of feature sets: %d", feature_sets);
2574 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302575 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002576 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302577
2578 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2579 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2580 if (!reply_skb) {
2581 hdd_err("Feature set matrix: buffer alloc fail");
2582 return -ENOMEM;
2583 }
2584
2585 if (nla_put_u32(reply_skb,
2586 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2587 feature_sets) ||
2588 nla_put(reply_skb,
2589 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2590 sizeof(u32) * feature_sets,
2591 feature_set_matrix)) {
2592 hdd_err("nla put fail");
2593 kfree_skb(reply_skb);
2594 return -EINVAL;
2595 }
2596 return cfg80211_vendor_cmd_reply(reply_skb);
2597}
2598
2599/**
2600 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2601 * @wiphy: pointer to wireless wiphy structure.
2602 * @wdev: pointer to wireless_dev structure.
2603 * @data: Pointer to the data to be passed via vendor interface
2604 * @data_len:Length of the data to be passed
2605 *
2606 * Retrieves the concurrency feature set matrix
2607 *
2608 * Return: 0 on success, negative errno on failure
2609 */
2610static int
2611wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2612 struct wireless_dev *wdev,
2613 const void *data,
2614 int data_len)
2615{
2616 int ret;
2617
2618 cds_ssr_protect(__func__);
2619 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2620 data, data_len);
2621 cds_ssr_unprotect(__func__);
2622
2623 return ret;
2624}
2625
2626/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002627 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2628 * @feature_flags: pointer to the byte array of features.
2629 * @feature: Feature to be turned ON in the byte array.
2630 *
2631 * Return: None
2632 *
2633 * This is called to turn ON or SET the feature flag for the requested feature.
2634 **/
2635#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002636static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2637 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002638{
2639 uint32_t index;
2640 uint8_t bit_mask;
2641
2642 index = feature / NUM_BITS_IN_BYTE;
2643 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2644 feature_flags[index] |= bit_mask;
2645}
2646
2647/**
2648 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2649 * @wiphy: pointer to wireless wiphy structure.
2650 * @wdev: pointer to wireless_dev structure.
2651 * @data: Pointer to the data to be passed via vendor interface
2652 * @data_len:Length of the data to be passed
2653 *
2654 * This is called when wlan driver needs to send supported feature set to
2655 * supplicant upon a request/query from the supplicant.
2656 *
2657 * Return: Return the Success or Failure code.
2658 **/
2659#define MAX_CONCURRENT_CHAN_ON_24G 2
2660#define MAX_CONCURRENT_CHAN_ON_5G 2
2661static int
2662__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2663 struct wireless_dev *wdev,
2664 const void *data, int data_len)
2665{
2666 struct sk_buff *skb = NULL;
2667 uint32_t dbs_capability = 0;
2668 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302669 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 int ret_val;
2671
2672 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2673 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2674
Jeff Johnson1f61b612016-02-12 16:28:33 -08002675 ENTER_DEV(wdev->netdev);
2676
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2678 if (ret_val)
2679 return ret_val;
2680
Anurag Chouhan6d760662016-02-20 16:05:43 +05302681 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682 hdd_err("Command not allowed in FTM mode");
2683 return -EPERM;
2684 }
2685
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002686 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002687 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688 wlan_hdd_cfg80211_set_feature(feature_flags,
2689 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2690 }
2691
2692 wlan_hdd_cfg80211_set_feature(feature_flags,
2693 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002694 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 wlan_hdd_cfg80211_set_feature(feature_flags,
2696 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002697
2698 if (wma_is_p2p_lo_capable())
2699 wlan_hdd_cfg80211_set_feature(feature_flags,
2700 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2701
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2703 NLMSG_HDRLEN);
2704
2705 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002706 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002707 return -ENOMEM;
2708 }
2709
2710 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2711 sizeof(feature_flags), feature_flags))
2712 goto nla_put_failure;
2713
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002714 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2715 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302716 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002717 if (one_by_one_dbs)
2718 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2719
2720 if (two_by_two_dbs)
2721 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2722
2723 if (!one_by_one_dbs && !two_by_two_dbs)
2724 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2725 } else {
2726 hdd_err("wma_get_dbs_hw_mode failed");
2727 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2728 }
2729
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002730 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731
2732 if (nla_put_u32(skb,
2733 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2734 MAX_CONCURRENT_CHAN_ON_24G))
2735 goto nla_put_failure;
2736
2737 if (nla_put_u32(skb,
2738 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2739 MAX_CONCURRENT_CHAN_ON_5G))
2740 goto nla_put_failure;
2741
2742 return cfg80211_vendor_cmd_reply(skb);
2743
2744nla_put_failure:
2745 kfree_skb(skb);
2746 return -EINVAL;
2747}
2748
2749/**
2750 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2751 * @wiphy: pointer to wireless wiphy structure.
2752 * @wdev: pointer to wireless_dev structure.
2753 * @data: Pointer to the data to be passed via vendor interface
2754 * @data_len:Length of the data to be passed
2755 *
2756 * This is called when wlan driver needs to send supported feature set to
2757 * supplicant upon a request/query from the supplicant.
2758 *
2759 * Return: Return the Success or Failure code.
2760 */
2761static int
2762wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2763 struct wireless_dev *wdev,
2764 const void *data, int data_len)
2765{
2766 int ret;
2767
2768 cds_ssr_protect(__func__);
2769 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2770 data, data_len);
2771 cds_ssr_unprotect(__func__);
2772
2773 return ret;
2774}
2775
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302776#define PARAM_NUM_NW \
2777 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2778#define PARAM_SET_BSSID \
2779 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2780#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2781#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782
2783/**
2784 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2785 * @wiphy: The wiphy structure
2786 * @wdev: The wireless device
2787 * @data: Data passed by framework
2788 * @data_len: Parameters to be configured passed as data
2789 *
2790 * The roaming related parameters are configured by the framework
2791 * using this interface.
2792 *
2793 * Return: Return either success or failure code.
2794 */
2795static int
2796__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2797 struct wireless_dev *wdev, const void *data, int data_len)
2798{
2799 struct net_device *dev = wdev->netdev;
2800 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2801 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2802 uint8_t session_id;
2803 struct roam_ext_params roam_params;
2804 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302805 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2807 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2808 int rem, i;
2809 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002810 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811 int ret;
2812
Jeff Johnson1f61b612016-02-12 16:28:33 -08002813 ENTER_DEV(dev);
2814
Anurag Chouhan6d760662016-02-20 16:05:43 +05302815 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 hdd_err("Command not allowed in FTM mode");
2817 return -EPERM;
2818 }
2819
2820 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302821 if (ret)
2822 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823
2824 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2825 data, data_len,
2826 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002827 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828 return -EINVAL;
2829 }
2830 /* Parse and fetch Command Type*/
2831 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002832 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002833 goto fail;
2834 }
2835 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302836 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002837 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2838 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002839 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002840 goto fail;
2841 }
2842 req_id = nla_get_u32(
2843 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002844 hdd_debug("Req Id (%d)", req_id);
2845 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002846 switch (cmd_type) {
2847 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2848 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302849 if (tb[PARAM_NUM_NW]) {
2850 count = nla_get_u32(
2851 tb[PARAM_NUM_NW]);
2852 } else {
2853 hdd_err("Number of networks is not provided");
2854 goto fail;
2855 }
2856
2857 if (count &&
2858 tb[PRAM_SSID_LIST]) {
2859 nla_for_each_nested(curr_attr,
2860 tb[PRAM_SSID_LIST], rem) {
2861 if (nla_parse(tb2,
2862 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2863 nla_data(curr_attr), nla_len(curr_attr),
2864 NULL)) {
2865 hdd_err("nla_parse failed");
2866 goto fail;
2867 }
2868 /* Parse and Fetch allowed SSID list*/
2869 if (!tb2[PARAM_LIST_SSID]) {
2870 hdd_err("attr allowed ssid failed");
2871 goto fail;
2872 }
2873 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2874 /*
2875 * Upper Layers include a null termination
2876 * character. Check for the actual permissible
2877 * length of SSID and also ensure not to copy
2878 * the NULL termination character to the driver
2879 * buffer.
2880 */
2881 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2882 ((buf_len - 1) <=
2883 SIR_MAC_MAX_SSID_LENGTH)) {
2884 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302886 tb2[PARAM_LIST_SSID], buf_len - 1);
2887 roam_params.ssid_allowed_list[i].length
2888 = buf_len - 1;
2889 hdd_debug("SSID[%d]: %.*s,length = %d",
2890 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 roam_params.ssid_allowed_list[i].length,
2892 roam_params.ssid_allowed_list[i].ssId,
2893 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302894 i++;
2895 } else {
2896 hdd_err("Invalid buffer length");
2897 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002898 }
2899 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302900 if (i != count) {
2901 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2902 i, count);
2903 goto fail;
2904 }
2905
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002906 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002907 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908 roam_params.num_ssid_allowed_list);
2909 sme_update_roam_params(pHddCtx->hHal, session_id,
2910 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2911 break;
2912 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2913 /* Parse and fetch 5G Boost Threshold */
2914 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002915 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916 goto fail;
2917 }
2918 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2919 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002920 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002921 roam_params.raise_rssi_thresh_5g);
2922 /* Parse and fetch 5G Penalty Threshold */
2923 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002924 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 goto fail;
2926 }
2927 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2928 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002929 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002930 roam_params.drop_rssi_thresh_5g);
2931 /* Parse and fetch 5G Boost Factor */
2932 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002933 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934 goto fail;
2935 }
2936 roam_params.raise_factor_5g = nla_get_u32(
2937 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002938 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002939 roam_params.raise_factor_5g);
2940 /* Parse and fetch 5G Penalty factor */
2941 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002942 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002943 goto fail;
2944 }
2945 roam_params.drop_factor_5g = nla_get_u32(
2946 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002947 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 roam_params.drop_factor_5g);
2949 /* Parse and fetch 5G Max Boost */
2950 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002951 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 goto fail;
2953 }
2954 roam_params.max_raise_rssi_5g = nla_get_u32(
2955 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002956 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 roam_params.max_raise_rssi_5g);
2958 /* Parse and fetch Rssi Diff */
2959 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002960 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002961 goto fail;
2962 }
2963 roam_params.rssi_diff = nla_get_s32(
2964 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002965 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002966 roam_params.rssi_diff);
2967 /* Parse and fetch Alert Rssi Threshold */
2968 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002969 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002970 goto fail;
2971 }
2972 roam_params.alert_rssi_threshold = nla_get_u32(
2973 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002974 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002975 roam_params.alert_rssi_threshold);
2976 sme_update_roam_params(pHddCtx->hHal, session_id,
2977 roam_params,
2978 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2979 break;
2980 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2981 /* Parse and fetch Activate Good Rssi Roam */
2982 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002983 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 goto fail;
2985 }
2986 roam_params.good_rssi_roam = nla_get_s32(
2987 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002988 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989 roam_params.good_rssi_roam);
2990 sme_update_roam_params(pHddCtx->hHal, session_id,
2991 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2992 break;
2993 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2994 /* Parse and fetch number of preferred BSSID */
2995 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002996 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002997 goto fail;
2998 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002999 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003000 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003001 if (count > MAX_BSSID_FAVORED) {
3002 hdd_err("Preferred BSSID count %u exceeds max %u",
3003 count, MAX_BSSID_FAVORED);
3004 goto fail;
3005 }
3006 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 i = 0;
3008 nla_for_each_nested(curr_attr,
3009 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3010 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003011
3012 if (i == count) {
3013 hdd_warn("Ignoring excess Preferred BSSID");
3014 break;
3015 }
3016
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 if (nla_parse(tb2,
3018 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3019 nla_data(curr_attr), nla_len(curr_attr),
3020 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003021 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003022 goto fail;
3023 }
3024 /* Parse and fetch MAC address */
3025 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003026 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 goto fail;
3028 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003029 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003030 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303031 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003032 hdd_debug(MAC_ADDRESS_STR,
3033 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 /* Parse and fetch preference factor*/
3035 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003036 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003037 goto fail;
3038 }
3039 roam_params.bssid_favored_factor[i] = nla_get_u32(
3040 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003041 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 roam_params.bssid_favored_factor[i]);
3043 i++;
3044 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003045 if (i < count)
3046 hdd_warn("Num Preferred BSSID %u less than expected %u",
3047 i, count);
3048 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 sme_update_roam_params(pHddCtx->hHal, session_id,
3050 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3051 break;
3052 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3053 /* Parse and fetch number of blacklist BSSID */
3054 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003055 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 goto fail;
3057 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003058 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003060 if (count > MAX_BSSID_AVOID_LIST) {
3061 hdd_err("Blacklist BSSID count %u exceeds max %u",
3062 count, MAX_BSSID_AVOID_LIST);
3063 goto fail;
3064 }
3065 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003066 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303067
3068 if (count &&
3069 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3070 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003071 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3072 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003073
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303074 if (i == count) {
3075 hdd_warn("Ignoring excess Blacklist BSSID");
3076 break;
3077 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003078
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303079 if (nla_parse(tb2,
3080 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3081 nla_data(curr_attr), nla_len(curr_attr),
3082 NULL)) {
3083 hdd_err("nla_parse failed");
3084 goto fail;
3085 }
3086 /* Parse and fetch MAC address */
3087 if (!tb2[PARAM_SET_BSSID]) {
3088 hdd_err("attr blacklist addr failed");
3089 goto fail;
3090 }
3091 nla_memcpy(
3092 roam_params.bssid_avoid_list[i].bytes,
3093 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3094 hdd_debug(MAC_ADDRESS_STR,
3095 MAC_ADDR_ARRAY(
3096 roam_params.bssid_avoid_list[i].bytes));
3097 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003100 if (i < count)
3101 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3102 i, count);
3103 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 sme_update_roam_params(pHddCtx->hHal, session_id,
3105 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3106 break;
3107 }
3108 return 0;
3109fail:
3110 return -EINVAL;
3111}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303112#undef PARAM_NUM_NW
3113#undef PARAM_SET_BSSID
3114#undef PRAM_SSID_LIST
3115#undef PARAM_LIST_SSID
3116
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003117
3118/**
3119 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3120 * @wiphy: pointer to wireless wiphy structure.
3121 * @wdev: pointer to wireless_dev structure.
3122 * @data: Pointer to the data to be passed via vendor interface
3123 * @data_len:Length of the data to be passed
3124 *
3125 * Return: Return the Success or Failure code.
3126 */
3127static int
3128wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3129 struct wireless_dev *wdev,
3130 const void *data,
3131 int data_len)
3132{
3133 int ret;
3134
3135 cds_ssr_protect(__func__);
3136 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3137 data, data_len);
3138 cds_ssr_unprotect(__func__);
3139
3140 return ret;
3141}
3142
3143static const struct nla_policy
3144wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3145 +1] = {
3146 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3147};
3148
3149/**
3150 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3151 * @hdd_ctx: HDD context
3152 * @device_mode: device mode
3153 * Return: bool
3154 */
3155static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003156 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157{
3158 hdd_adapter_t *adapter;
3159 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3160 hdd_ap_ctx_t *ap_ctx;
3161 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303162 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303164 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003165 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303167 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 adapter = adapter_node->pAdapter;
3169
3170 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003171 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 ap_ctx =
3173 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3174
3175 /*
3176 * if there is SAP already running on DFS channel,
3177 * do not disable scan on dfs channels. Note that
3178 * with SAP on DFS, there cannot be conurrency on
3179 * single radio. But then we can have multiple
3180 * radios !!
3181 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003182 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3183 hdd_ctx->hdd_pdev,
3184 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003185 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186 return true;
3187 }
3188 }
3189
3190 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003191 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 sta_ctx =
3193 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3194
3195 /*
3196 * if STA is already connected on DFS channel,
3197 * do not disable scan on dfs channels
3198 */
3199 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003200 (CHANNEL_STATE_DFS ==
3201 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3202 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003203 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003204 return true;
3205 }
3206 }
3207
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303208 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003209 adapter_node,
3210 &next);
3211 adapter_node = next;
3212 }
3213
3214 return false;
3215}
3216
3217/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003218 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3219 * @hdd_ctx: HDD context within host driver
3220 * @adapter: Adapter pointer
3221 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3222 *
3223 * Loops through devices to see who is operating on DFS channels
3224 * and then disables/enables DFS channels by calling SME API.
3225 * Fails the disable request if any device is active on a DFS channel.
3226 *
3227 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003229
3230int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3231 hdd_adapter_t *adapter,
3232 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303235 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237
3238 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3239 if (no_dfs_flag) {
3240 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003241 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242
3243 if (true == status)
3244 return -EOPNOTSUPP;
3245
3246 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003247 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248
3249 if (true == status)
3250 return -EOPNOTSUPP;
3251 }
3252
3253 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3254
3255 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3256
3257 /*
3258 * call the SME API to tunnel down the new channel list
3259 * to the firmware
3260 */
3261 status = sme_handle_dfs_chan_scan(
3262 h_hal, hdd_ctx->config->enableDFSChnlScan);
3263
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303264 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003265 ret_val = 0;
3266
3267 /*
3268 * Clear the SME scan cache also. Note that the
3269 * clearing of scan results is independent of session;
3270 * so no need to iterate over
3271 * all sessions
3272 */
3273 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303274 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003275 ret_val = -EPERM;
3276 }
3277
3278 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003279 hdd_debug(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 ret_val = 0;
3281 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003282 return ret_val;
3283}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003285/**
3286 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3287 * @wiphy: corestack handler
3288 * @wdev: wireless device
3289 * @data: data
3290 * @data_len: data length
3291 * Return: success(0) or reason code for failure
3292 */
3293static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3294 struct wireless_dev *wdev,
3295 const void *data,
3296 int data_len)
3297{
3298 struct net_device *dev = wdev->netdev;
3299 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3300 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3301 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3302 int ret_val;
3303 uint32_t no_dfs_flag = 0;
3304
Jeff Johnson1f61b612016-02-12 16:28:33 -08003305 ENTER_DEV(dev);
3306
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003307 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303308 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003309 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003310
3311 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3312 data, data_len,
3313 wlan_hdd_set_no_dfs_flag_config_policy)) {
3314 hdd_err("invalid attr");
3315 return -EINVAL;
3316 }
3317
3318 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3319 hdd_err("attr dfs flag failed");
3320 return -EINVAL;
3321 }
3322
3323 no_dfs_flag = nla_get_u32(
3324 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3325
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003326 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003327
3328 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003329 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003330 return -EINVAL;
3331 }
3332
3333 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3334 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335 return ret_val;
3336}
3337
3338/**
3339 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3340 *
3341 * @wiphy: wiphy device pointer
3342 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003343 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003344 * @data_len: Buffer length
3345 *
3346 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3347 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3348 *
3349 * Return: EOK or other error codes.
3350 */
3351
3352static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3353 struct wireless_dev *wdev,
3354 const void *data,
3355 int data_len)
3356{
3357 int ret;
3358
3359 cds_ssr_protect(__func__);
3360 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3361 data, data_len);
3362 cds_ssr_unprotect(__func__);
3363
3364 return ret;
3365}
3366
Manikandan Mohan80dea792016-04-28 16:36:48 -07003367static const struct nla_policy
3368wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3369 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3370};
3371
3372/**
3373 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3374 * @wiphy: wiphy device pointer
3375 * @wdev: wireless device pointer
3376 * @data: Vendor command data buffer
3377 * @data_len: Buffer length
3378 *
3379 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3380 * setup WISA Mode features.
3381 *
3382 * Return: Success(0) or reason code for failure
3383 */
3384static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3385 struct wireless_dev *wdev, const void *data, int data_len)
3386{
3387 struct net_device *dev = wdev->netdev;
3388 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3389 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3390 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3391 struct sir_wisa_params wisa;
3392 int ret_val;
3393 QDF_STATUS status;
3394 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003395 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3396 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003397
3398 ENTER_DEV(dev);
3399 ret_val = wlan_hdd_validate_context(hdd_ctx);
3400 if (ret_val)
3401 goto err;
3402
3403 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3404 hdd_err("Command not allowed in FTM mode");
3405 return -EPERM;
3406 }
3407
3408 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3409 wlan_hdd_wisa_cmd_policy)) {
3410 hdd_err("Invalid WISA cmd attributes");
3411 ret_val = -EINVAL;
3412 goto err;
3413 }
3414 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3415 hdd_err("Invalid WISA mode");
3416 ret_val = -EINVAL;
3417 goto err;
3418 }
3419
3420 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003421 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003422 wisa.mode = wisa_mode;
3423 wisa.vdev_id = adapter->sessionId;
3424 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003425 if (!QDF_IS_STATUS_SUCCESS(status)) {
3426 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003427 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003428 }
3429 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003430 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003431 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3432 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003433 adapter->sessionId),
3434 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003435err:
3436 EXIT();
3437 return ret_val;
3438}
3439
3440/**
3441 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3442 * @wiphy: corestack handler
3443 * @wdev: wireless device
3444 * @data: data
3445 * @data_len: data length
3446 *
3447 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3448 * setup WISA mode features.
3449 *
3450 * Return: Success(0) or reason code for failure
3451 */
3452static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3453 struct wireless_dev *wdev,
3454 const void *data,
3455 int data_len)
3456{
3457 int ret;
3458
3459 cds_ssr_protect(__func__);
3460 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3461 cds_ssr_unprotect(__func__);
3462
3463 return ret;
3464}
3465
Anurag Chouhan96919482016-07-13 16:36:57 +05303466/*
3467 * define short names for the global vendor params
3468 * used by __wlan_hdd_cfg80211_get_station_cmd()
3469 */
3470#define STATION_INVALID \
3471 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3472#define STATION_INFO \
3473 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3474#define STATION_ASSOC_FAIL_REASON \
3475 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3476#define STATION_MAX \
3477 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3478
3479static const struct nla_policy
3480hdd_get_station_policy[STATION_MAX + 1] = {
3481 [STATION_INFO] = {.type = NLA_FLAG},
3482 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3483};
3484
3485/**
3486 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3487 * @hdd_ctx: HDD context within host driver
3488 * @wdev: wireless device
3489 *
3490 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3491 * Validate cmd attributes and send the station info to upper layers.
3492 *
3493 * Return: Success(0) or reason code for failure
3494 */
3495static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3496 hdd_adapter_t *adapter)
3497{
3498 struct sk_buff *skb = NULL;
3499 uint32_t nl_buf_len;
3500 hdd_station_ctx_t *hdd_sta_ctx;
3501
3502 nl_buf_len = NLMSG_HDRLEN;
3503 nl_buf_len += sizeof(uint32_t);
3504 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3505
3506 if (!skb) {
3507 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3508 return -ENOMEM;
3509 }
3510
3511 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3512
3513 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3514 hdd_sta_ctx->conn_info.assoc_status_code)) {
3515 hdd_err("put fail");
3516 goto fail;
3517 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303518
3519 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3520 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3521 hdd_sta_ctx->conn_info.cca)) {
3522 hdd_err("put fail");
3523 goto fail;
3524 }
3525
Anurag Chouhan96919482016-07-13 16:36:57 +05303526 return cfg80211_vendor_cmd_reply(skb);
3527fail:
3528 if (skb)
3529 kfree_skb(skb);
3530 return -EINVAL;
3531}
3532
3533/**
3534 * hdd_map_auth_type() - transform auth type specific to
3535 * vendor command
3536 * @auth_type: csr auth type
3537 *
3538 * Return: Success(0) or reason code for failure
3539 */
3540static int hdd_convert_auth_type(uint32_t auth_type)
3541{
3542 uint32_t ret_val;
3543
3544 switch (auth_type) {
3545 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3546 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3547 break;
3548 case eCSR_AUTH_TYPE_SHARED_KEY:
3549 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3550 break;
3551 case eCSR_AUTH_TYPE_WPA:
3552 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3553 break;
3554 case eCSR_AUTH_TYPE_WPA_PSK:
3555 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3556 break;
3557 case eCSR_AUTH_TYPE_AUTOSWITCH:
3558 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3559 break;
3560 case eCSR_AUTH_TYPE_WPA_NONE:
3561 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3562 break;
3563 case eCSR_AUTH_TYPE_RSN:
3564 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3565 break;
3566 case eCSR_AUTH_TYPE_RSN_PSK:
3567 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3568 break;
3569 case eCSR_AUTH_TYPE_FT_RSN:
3570 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3571 break;
3572 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3573 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3574 break;
3575 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3576 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3577 break;
3578 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3579 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3580 break;
3581 case eCSR_AUTH_TYPE_CCKM_WPA:
3582 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3583 break;
3584 case eCSR_AUTH_TYPE_CCKM_RSN:
3585 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3586 break;
3587 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3588 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3589 break;
3590 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3591 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3592 break;
3593 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3594 case eCSR_AUTH_TYPE_FAILED:
3595 case eCSR_AUTH_TYPE_NONE:
3596 default:
3597 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3598 break;
3599 }
3600 return ret_val;
3601}
3602
3603/**
3604 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3605 * vendor command
3606 * @dot11mode: dot11mode
3607 *
3608 * Return: Success(0) or reason code for failure
3609 */
3610static int hdd_convert_dot11mode(uint32_t dot11mode)
3611{
3612 uint32_t ret_val;
3613
3614 switch (dot11mode) {
3615 case eCSR_CFG_DOT11_MODE_11A:
3616 ret_val = QCA_WLAN_802_11_MODE_11A;
3617 break;
3618 case eCSR_CFG_DOT11_MODE_11B:
3619 ret_val = QCA_WLAN_802_11_MODE_11B;
3620 break;
3621 case eCSR_CFG_DOT11_MODE_11G:
3622 ret_val = QCA_WLAN_802_11_MODE_11G;
3623 break;
3624 case eCSR_CFG_DOT11_MODE_11N:
3625 ret_val = QCA_WLAN_802_11_MODE_11N;
3626 break;
3627 case eCSR_CFG_DOT11_MODE_11AC:
3628 ret_val = QCA_WLAN_802_11_MODE_11AC;
3629 break;
3630 case eCSR_CFG_DOT11_MODE_AUTO:
3631 case eCSR_CFG_DOT11_MODE_ABG:
3632 default:
3633 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3634 }
3635 return ret_val;
3636}
3637
3638/**
3639 * hdd_add_tx_bitrate() - add tx bitrate attribute
3640 * @skb: pointer to sk buff
3641 * @hdd_sta_ctx: pointer to hdd station context
3642 * @idx: attribute index
3643 *
3644 * Return: Success(0) or reason code for failure
3645 */
3646static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3647 hdd_station_ctx_t *hdd_sta_ctx,
3648 int idx)
3649{
3650 struct nlattr *nla_attr;
3651 uint32_t bitrate, bitrate_compat;
3652
3653 nla_attr = nla_nest_start(skb, idx);
3654 if (!nla_attr)
3655 goto fail;
3656 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3657 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3658
3659 /* report 16-bit bitrate only if we can */
3660 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3661 if (bitrate > 0 &&
3662 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3663 hdd_err("put fail");
3664 goto fail;
3665 }
3666 if (bitrate_compat > 0 &&
3667 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3668 hdd_err("put fail");
3669 goto fail;
3670 }
3671 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3672 hdd_sta_ctx->conn_info.txrate.nss)) {
3673 hdd_err("put fail");
3674 goto fail;
3675 }
3676 nla_nest_end(skb, nla_attr);
3677 return 0;
3678fail:
3679 return -EINVAL;
3680}
3681
3682/**
3683 * hdd_add_sta_info() - add station info attribute
3684 * @skb: pointer to sk buff
3685 * @hdd_sta_ctx: pointer to hdd station context
3686 * @idx: attribute index
3687 *
3688 * Return: Success(0) or reason code for failure
3689 */
3690static int32_t hdd_add_sta_info(struct sk_buff *skb,
3691 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3692{
3693 struct nlattr *nla_attr;
3694
3695 nla_attr = nla_nest_start(skb, idx);
3696 if (!nla_attr)
3697 goto fail;
3698 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3699 (hdd_sta_ctx->conn_info.signal + 100))) {
3700 hdd_err("put fail");
3701 goto fail;
3702 }
3703 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3704 goto fail;
3705 nla_nest_end(skb, nla_attr);
3706 return 0;
3707fail:
3708 return -EINVAL;
3709}
3710
3711/**
3712 * hdd_add_survey_info() - add survey info attribute
3713 * @skb: pointer to sk buff
3714 * @hdd_sta_ctx: pointer to hdd station context
3715 * @idx: attribute index
3716 *
3717 * Return: Success(0) or reason code for failure
3718 */
3719static int32_t hdd_add_survey_info(struct sk_buff *skb,
3720 hdd_station_ctx_t *hdd_sta_ctx,
3721 int idx)
3722{
3723 struct nlattr *nla_attr;
3724
3725 nla_attr = nla_nest_start(skb, idx);
3726 if (!nla_attr)
3727 goto fail;
3728 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3729 hdd_sta_ctx->conn_info.freq) ||
3730 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3731 (hdd_sta_ctx->conn_info.noise + 100))) {
3732 hdd_err("put fail");
3733 goto fail;
3734 }
3735 nla_nest_end(skb, nla_attr);
3736 return 0;
3737fail:
3738 return -EINVAL;
3739}
3740
3741/**
3742 * hdd_add_link_standard_info() - add link info attribute
3743 * @skb: pointer to sk buff
3744 * @hdd_sta_ctx: pointer to hdd station context
3745 * @idx: attribute index
3746 *
3747 * Return: Success(0) or reason code for failure
3748 */
3749static int32_t
3750hdd_add_link_standard_info(struct sk_buff *skb,
3751 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3752{
3753 struct nlattr *nla_attr;
3754
3755 nla_attr = nla_nest_start(skb, idx);
3756 if (!nla_attr)
3757 goto fail;
3758 if (nla_put(skb,
3759 NL80211_ATTR_SSID,
3760 hdd_sta_ctx->conn_info.SSID.SSID.length,
3761 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3762 hdd_err("put fail");
3763 goto fail;
3764 }
3765 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3766 goto fail;
3767 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3768 goto fail;
3769 nla_nest_end(skb, nla_attr);
3770 return 0;
3771fail:
3772 return -EINVAL;
3773}
3774
3775/**
3776 * hdd_add_ap_standard_info() - add ap info attribute
3777 * @skb: pointer to sk buff
3778 * @hdd_sta_ctx: pointer to hdd station context
3779 * @idx: attribute index
3780 *
3781 * Return: Success(0) or reason code for failure
3782 */
3783static int32_t
3784hdd_add_ap_standard_info(struct sk_buff *skb,
3785 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3786{
3787 struct nlattr *nla_attr;
3788
3789 nla_attr = nla_nest_start(skb, idx);
3790 if (!nla_attr)
3791 goto fail;
3792 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3793 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3794 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3795 &hdd_sta_ctx->conn_info.vht_caps)) {
3796 hdd_err("put fail");
3797 goto fail;
3798 }
3799 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3800 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3801 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3802 &hdd_sta_ctx->conn_info.ht_caps)) {
3803 hdd_err("put fail");
3804 goto fail;
3805 }
3806 nla_nest_end(skb, nla_attr);
3807 return 0;
3808fail:
3809 return -EINVAL;
3810}
3811
3812/**
3813 * hdd_get_station_info() - send BSS information to supplicant
3814 * @hdd_ctx: pointer to hdd context
3815 * @adapter: pointer to adapter
3816 *
3817 * Return: 0 if success else error status
3818 */
3819static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3820 hdd_adapter_t *adapter)
3821{
3822 struct sk_buff *skb = NULL;
3823 uint8_t *tmp_hs20 = NULL;
3824 uint32_t nl_buf_len;
3825 hdd_station_ctx_t *hdd_sta_ctx;
3826
3827 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3828
3829 nl_buf_len = NLMSG_HDRLEN;
3830 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3831 sizeof(hdd_sta_ctx->conn_info.freq) +
3832 sizeof(hdd_sta_ctx->conn_info.noise) +
3833 sizeof(hdd_sta_ctx->conn_info.signal) +
3834 (sizeof(uint32_t) * 2) +
3835 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3836 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3837 sizeof(hdd_sta_ctx->conn_info.authType) +
3838 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3839 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3840 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3841 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3842 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3843 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3844 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3845 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3846 1);
3847 }
3848 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3849 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3850 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3851 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3852
3853
3854 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3855 if (!skb) {
3856 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3857 return -ENOMEM;
3858 }
3859
3860 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3861 LINK_INFO_STANDARD_NL80211_ATTR)) {
3862 hdd_err("put fail");
3863 goto fail;
3864 }
3865 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3866 AP_INFO_STANDARD_NL80211_ATTR)) {
3867 hdd_err("put fail");
3868 goto fail;
3869 }
3870 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3871 hdd_sta_ctx->conn_info.roam_count) ||
3872 nla_put_u32(skb, INFO_AKM,
3873 hdd_convert_auth_type(
3874 hdd_sta_ctx->conn_info.authType)) ||
3875 nla_put_u32(skb, WLAN802_11_MODE,
3876 hdd_convert_dot11mode(
3877 hdd_sta_ctx->conn_info.dot11Mode))) {
3878 hdd_err("put fail");
3879 goto fail;
3880 }
3881 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3882 if (nla_put(skb, HT_OPERATION,
3883 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3884 &hdd_sta_ctx->conn_info.ht_operation)) {
3885 hdd_err("put fail");
3886 goto fail;
3887 }
3888 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3889 if (nla_put(skb, VHT_OPERATION,
3890 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3891 &hdd_sta_ctx->conn_info.vht_operation)) {
3892 hdd_err("put fail");
3893 goto fail;
3894 }
3895 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3896 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3897 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3898 tmp_hs20 + 1)) {
3899 hdd_err("put fail");
3900 goto fail;
3901 }
3902
3903 return cfg80211_vendor_cmd_reply(skb);
3904fail:
3905 if (skb)
3906 kfree_skb(skb);
3907 return -EINVAL;
3908}
3909
3910/**
3911 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3912 * @wiphy: corestack handler
3913 * @wdev: wireless device
3914 * @data: data
3915 * @data_len: data length
3916 *
3917 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3918 * Validate cmd attributes and send the station info to upper layers.
3919 *
3920 * Return: Success(0) or reason code for failure
3921 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303922static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303923__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3924 struct wireless_dev *wdev,
3925 const void *data,
3926 int data_len)
3927{
3928 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3929 struct net_device *dev = wdev->netdev;
3930 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3931 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3932 int32_t status;
3933
3934 ENTER_DEV(dev);
3935 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3936 hdd_err("Command not allowed in FTM mode");
3937 status = -EPERM;
3938 goto out;
3939 }
3940
3941 status = wlan_hdd_validate_context(hdd_ctx);
3942 if (0 != status)
3943 goto out;
3944
3945
3946 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3947 data, data_len, NULL);
3948 if (status) {
3949 hdd_err("Invalid ATTR");
3950 goto out;
3951 }
3952
3953 /* Parse and fetch Command Type*/
3954 if (tb[STATION_INFO]) {
3955 status = hdd_get_station_info(hdd_ctx, adapter);
3956 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3957 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3958 } else {
3959 hdd_err("get station info cmd type failed");
3960 status = -EINVAL;
3961 goto out;
3962 }
3963 EXIT();
3964out:
3965 return status;
3966}
3967
3968/**
3969 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3970 * @wiphy: corestack handler
3971 * @wdev: wireless device
3972 * @data: data
3973 * @data_len: data length
3974 *
3975 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3976 * Validate cmd attributes and send the station info to upper layers.
3977 *
3978 * Return: Success(0) or reason code for failure
3979 */
3980static int32_t
3981hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3982 struct wireless_dev *wdev,
3983 const void *data,
3984 int data_len)
3985{
3986 int ret;
3987
3988 cds_ssr_protect(__func__);
3989 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3990 cds_ssr_unprotect(__func__);
3991
3992 return ret;
3993}
3994
3995/*
3996 * undef short names defined for get station command
3997 * used by __wlan_hdd_cfg80211_get_station_cmd()
3998 */
3999#undef STATION_INVALID
4000#undef STATION_INFO
4001#undef STATION_ASSOC_FAIL_REASON
4002#undef STATION_MAX
4003
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004004#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4005/**
4006 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4007 * @wiphy: pointer to wireless wiphy structure.
4008 * @wdev: pointer to wireless_dev structure.
4009 * @data: Pointer to the Key data
4010 * @data_len:Length of the data passed
4011 *
4012 * This is called when wlan driver needs to save the keys received via
4013 * vendor specific command.
4014 *
4015 * Return: Return the Success or Failure code.
4016 */
4017static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4018 struct wireless_dev *wdev,
4019 const void *data, int data_len)
4020{
4021 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4022 struct net_device *dev = wdev->netdev;
4023 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4024 hdd_context_t *hdd_ctx_ptr;
4025 int status;
4026
Jeff Johnson1f61b612016-02-12 16:28:33 -08004027 ENTER_DEV(dev);
4028
Anurag Chouhan6d760662016-02-20 16:05:43 +05304029 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004030 hdd_err("Command not allowed in FTM mode");
4031 return -EPERM;
4032 }
4033
4034 if ((data == NULL) || (data_len == 0) ||
4035 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004036 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037 return -EINVAL;
4038 }
4039
4040 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4041 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004042 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 return -EINVAL;
4044 }
4045
4046 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304047 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4050 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004051 true,
4052 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304053 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4054 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004055 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4056 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4057 return 0;
4058}
4059
4060/**
4061 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4062 * @wiphy: pointer to wireless wiphy structure.
4063 * @wdev: pointer to wireless_dev structure.
4064 * @data: Pointer to the Key data
4065 * @data_len:Length of the data passed
4066 *
4067 * This is called when wlan driver needs to save the keys received via
4068 * vendor specific command.
4069 *
4070 * Return: Return the Success or Failure code.
4071 */
4072static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4073 struct wireless_dev *wdev,
4074 const void *data, int data_len)
4075{
4076 int ret;
4077
4078 cds_ssr_protect(__func__);
4079 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4080 cds_ssr_unprotect(__func__);
4081
4082 return ret;
4083}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004084#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004085
4086static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4087 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4088 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4089 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004090 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091};
4092
4093/**
4094 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4095 * @wiphy: pointer to wireless wiphy structure.
4096 * @wdev: pointer to wireless_dev structure.
4097 * @data: Pointer to the data to be passed via vendor interface
4098 * @data_len:Length of the data to be passed
4099 *
4100 * This is called when wlan driver needs to send wifi driver related info
4101 * (driver/fw version) to the user space application upon request.
4102 *
4103 * Return: Return the Success or Failure code.
4104 */
4105static int
4106__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4107 struct wireless_dev *wdev,
4108 const void *data, int data_len)
4109{
4110 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4111 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004112 tSirVersionString driver_version;
4113 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004116 struct sk_buff *reply_skb;
4117 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004118
Jeff Johnson1f61b612016-02-12 16:28:33 -08004119 ENTER_DEV(wdev->netdev);
4120
Anurag Chouhan6d760662016-02-20 16:05:43 +05304121 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004122 hdd_err("Command not allowed in FTM mode");
4123 return -EPERM;
4124 }
4125
4126 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304127 if (status)
4128 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004129
4130 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4131 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004132 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004133 return -EINVAL;
4134 }
4135
4136 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004137 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004138 strlcpy(driver_version, QWLAN_VERSIONSTR,
4139 sizeof(driver_version));
4140 skb_len += strlen(driver_version) + 1;
4141 count++;
4142 }
4143
4144 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004145 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004146 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4147 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004148 snprintf(firmware_version, sizeof(firmware_version),
4149 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4150 skb_len += strlen(firmware_version) + 1;
4151 count++;
4152 }
4153
4154 if (count == 0) {
4155 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004156 return -EINVAL;
4157 }
4158
Ryan Hsu7ac88852016-04-28 10:20:34 -07004159 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4160 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4161
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004162 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004163 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 return -ENOMEM;
4165 }
4166
Ryan Hsu7ac88852016-04-28 10:20:34 -07004167 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4168 if (nla_put_string(reply_skb,
4169 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4170 driver_version))
4171 goto error_nla_fail;
4172 }
4173
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304174 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004175 if (nla_put_string(reply_skb,
4176 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4177 firmware_version))
4178 goto error_nla_fail;
4179 }
4180
4181 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4182 if (nla_put_u32(reply_skb,
4183 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4184 hdd_ctx->radio_index))
4185 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004186 }
4187
4188 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004189
4190error_nla_fail:
4191 hdd_err("nla put fail");
4192 kfree_skb(reply_skb);
4193 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004194}
4195
4196/**
4197 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4198 * @wiphy: pointer to wireless wiphy structure.
4199 * @wdev: pointer to wireless_dev structure.
4200 * @data: Pointer to the data to be passed via vendor interface
4201 * @data_len:Length of the data to be passed
4202 *
4203 * This is called when wlan driver needs to send wifi driver related info
4204 * (driver/fw version) to the user space application upon request.
4205 *
4206 * Return: Return the Success or Failure code.
4207 */
4208static int
4209wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4210 struct wireless_dev *wdev,
4211 const void *data, int data_len)
4212{
4213 int ret;
4214
4215 cds_ssr_protect(__func__);
4216 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4217 cds_ssr_unprotect(__func__);
4218
4219 return ret;
4220}
4221
4222/**
4223 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4224 * @wiphy: pointer to wireless wiphy structure.
4225 * @wdev: pointer to wireless_dev structure.
4226 * @data: Pointer to the data to be passed via vendor interface
4227 * @data_len:Length of the data to be passed
4228 *
4229 * This is called by userspace to know the supported logger features
4230 *
4231 * Return: Return the Success or Failure code.
4232 */
4233static int
4234__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4235 struct wireless_dev *wdev,
4236 const void *data, int data_len)
4237{
4238 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4239 int status;
4240 uint32_t features;
4241 struct sk_buff *reply_skb = NULL;
4242
Jeff Johnson1f61b612016-02-12 16:28:33 -08004243 ENTER_DEV(wdev->netdev);
4244
Anurag Chouhan6d760662016-02-20 16:05:43 +05304245 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004246 hdd_err("Command not allowed in FTM mode");
4247 return -EPERM;
4248 }
4249
4250 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304251 if (status)
4252 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253
4254 features = 0;
4255
4256 if (hdd_is_memdump_supported())
4257 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4258 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4259 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4260 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4261
4262 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4263 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4264 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004265 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004266 return -ENOMEM;
4267 }
4268
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004269 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004270 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4271 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004272 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004273 kfree_skb(reply_skb);
4274 return -EINVAL;
4275 }
4276
4277 return cfg80211_vendor_cmd_reply(reply_skb);
4278}
4279
4280/**
4281 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4282 * @wiphy: pointer to wireless wiphy structure.
4283 * @wdev: pointer to wireless_dev structure.
4284 * @data: Pointer to the data to be passed via vendor interface
4285 * @data_len:Length of the data to be passed
4286 *
4287 * This is called by userspace to know the supported logger features
4288 *
4289 * Return: Return the Success or Failure code.
4290 */
4291static int
4292wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4293 struct wireless_dev *wdev,
4294 const void *data, int data_len)
4295{
4296 int ret;
4297
4298 cds_ssr_protect(__func__);
4299 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4300 data, data_len);
4301 cds_ssr_unprotect(__func__);
4302
4303 return ret;
4304}
4305
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004306#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004307/**
4308 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304309 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004310 * @bssid: pointer to bssid of roamed AP.
4311 * @req_rsn_ie: Pointer to request RSN IE
4312 * @req_rsn_len: Length of the request RSN IE
4313 * @rsp_rsn_ie: Pointer to response RSN IE
4314 * @rsp_rsn_len: Length of the response RSN IE
4315 * @roam_info_ptr: Pointer to the roaming related information
4316 *
4317 * This is called when wlan driver needs to send the roaming and
4318 * authorization information after roaming.
4319 *
4320 * The information that would be sent is the request RSN IE, response
4321 * RSN IE and BSSID of the newly roamed AP.
4322 *
4323 * If the Authorized status is authenticated, then additional parameters
4324 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4325 * supplicant.
4326 *
4327 * The supplicant upon receiving this event would ignore the legacy
4328 * cfg80211_roamed call and use the entire information from this event.
4329 * The cfg80211_roamed should still co-exist since the kernel will
4330 * make use of the parameters even if the supplicant ignores it.
4331 *
4332 * Return: Return the Success or Failure code.
4333 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304334int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4336 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4337{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304338 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004339 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004340 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004341 ENTER();
4342
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304343 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004344 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004346 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004347 !roam_info_ptr->roamSynchInProgress)
4348 return 0;
4349
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004350 /*
4351 * The user space has issued a disconnect when roaming is in
4352 * progress. The disconnect should be honored gracefully.
4353 * If the roaming is complete and the roam event is sent
4354 * back to the user space, it will get confused as it is
4355 * expecting a disconnect event. So, do not send the event
4356 * and handle the disconnect later.
4357 */
4358 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004359 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004360 return 0;
4361 }
4362
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004363 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304364 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4366 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4367 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004368 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004369 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4370 GFP_KERNEL);
4371
4372 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004373 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004374 return -EINVAL;
4375 }
4376
4377 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4378 ETH_ALEN, bssid) ||
4379 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4380 req_rsn_len, req_rsn_ie) ||
4381 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4382 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004383 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004384 goto nla_put_failure;
4385 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004386 if (roam_info_ptr->synchAuthStatus ==
4387 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004388 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004389 if (nla_put_u8(skb,
4390 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4391 hdd_err("nla put fail");
4392 goto nla_put_failure;
4393 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004394 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4395 /* if FT or CCKM connection: dont send replay counter */
4396 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4397 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4398 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4399 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4400 nla_put(skb,
4401 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4402 SIR_REPLAY_CTR_LEN,
4403 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004404 hdd_err("non FT/non CCKM connection");
4405 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004406 goto nla_put_failure;
4407 }
4408 if (nla_put(skb,
4409 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4410 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4411 nla_put(skb,
4412 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4413 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4414 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415 goto nla_put_failure;
4416 }
4417 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004418 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004419 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4420 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004421 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004422 goto nla_put_failure;
4423 }
4424 }
4425
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304426 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4427 roam_info_ptr->synchAuthStatus,
4428 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004429
4430 /*
4431 * Add subnet change status if subnet has changed
4432 * 0 = unchanged
4433 * 1 = changed
4434 * 2 = unknown
4435 */
4436 if (roam_info_ptr->subnet_change_status) {
4437 if (nla_put_u8(skb,
4438 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4439 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004440 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004441 goto nla_put_failure;
4442 }
4443 }
4444
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004445 cfg80211_vendor_event(skb, GFP_KERNEL);
4446 return 0;
4447
4448nla_put_failure:
4449 kfree_skb(skb);
4450 return -EINVAL;
4451}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004452#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004453
4454static const struct nla_policy
4455wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4456
4457 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4458 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4459 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304460 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304461 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4462 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004463 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4464 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4465 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4466 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4467 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304468 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004469};
4470
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004471/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304472 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4473 *
4474 * @adapter: Pointer to HDD adapter
4475 * @ie_data: Pointer to Scan IEs buffer
4476 * @ie_len: Length of Scan IEs
4477 *
4478 * Return: 0 on success; error number otherwise
4479 */
4480static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4481 uint8_t *ie_data, uint8_t ie_len)
4482{
4483 hdd_scaninfo_t *scan_info = NULL;
4484 scan_info = &adapter->scan_info;
4485
4486 if (scan_info->default_scan_ies) {
4487 qdf_mem_free(scan_info->default_scan_ies);
4488 scan_info->default_scan_ies = NULL;
4489 }
4490
4491 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4492 if (!scan_info->default_scan_ies)
4493 return -ENOMEM;
4494
4495 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4496 scan_info->default_scan_ies_len = ie_len;
4497 return 0;
4498}
4499
4500/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004501 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4502 * vendor command
4503 *
4504 * @wiphy: wiphy device pointer
4505 * @wdev: wireless device pointer
4506 * @data: Vendor command data buffer
4507 * @data_len: Buffer length
4508 *
4509 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4510 *
4511 * Return: Error code.
4512 */
4513static int
4514__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4515 struct wireless_dev *wdev,
4516 const void *data,
4517 int data_len)
4518{
4519 struct net_device *dev = wdev->netdev;
4520 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4521 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4522 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4523 int ret_val = 0;
4524 u32 modulated_dtim;
4525 u16 stats_avg_factor;
4526 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304527 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004528 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004529 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304530 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304531 int attr_len;
4532 int access_policy = 0;
4533 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4534 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304535 uint16_t scan_ie_len = 0;
4536 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304537 struct sir_set_tx_rx_aggregation_size request;
4538 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004539 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004540 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004541 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304542 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304543
Jeff Johnson1f61b612016-02-12 16:28:33 -08004544 ENTER_DEV(dev);
4545
Anurag Chouhan6d760662016-02-20 16:05:43 +05304546 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004547 hdd_err("Command not allowed in FTM mode");
4548 return -EPERM;
4549 }
4550
4551 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304552 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004553 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554
4555 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4556 data, data_len,
4557 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004558 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004559 return -EINVAL;
4560 }
4561
Krunal Sonie3531942016-04-12 17:43:53 -07004562 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4563 ftm_capab = nla_get_u32(tb[
4564 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4565 hdd_ctx->config->fine_time_meas_cap =
4566 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4567 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304568 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004569 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004570 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4571 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004572 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004573 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4574 hdd_ctx->config->fine_time_meas_cap);
4575 }
4576
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004577 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4578 modulated_dtim = nla_get_u32(
4579 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4580
4581 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4582 adapter->sessionId,
4583 modulated_dtim);
4584
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304585 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004586 ret_val = -EPERM;
4587 }
4588
Kapil Gupta6213c012016-09-02 19:39:09 +05304589 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4590 qpower = nla_get_u8(
4591 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4592 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4593 ret_val = -EINVAL;
4594 }
4595
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004596 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4597 stats_avg_factor = nla_get_u16(
4598 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4599 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4600 adapter->sessionId,
4601 stats_avg_factor);
4602
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304603 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004604 ret_val = -EPERM;
4605 }
4606
4607
4608 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4609 guard_time = nla_get_u32(
4610 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4611 status = sme_configure_guard_time(hdd_ctx->hHal,
4612 adapter->sessionId,
4613 guard_time);
4614
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304615 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616 ret_val = -EPERM;
4617 }
4618
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304619 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4620 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4621 attr_len = nla_len(
4622 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4623 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004624 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304625 attr_len);
4626 return -EINVAL;
4627 }
4628
4629 nla_memcpy(&vendor_ie,
4630 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4631 attr_len);
4632 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004633 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304634 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304635 }
4636
4637 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4638 access_policy = (int) nla_get_u32(
4639 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4640 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4641 (access_policy >
4642 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004643 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304644 access_policy);
4645 return -EINVAL;
4646 }
4647 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004648 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304649 access_policy);
4650 }
4651
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004652 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4653 retry = nla_get_u8(tb[
4654 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4655 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4656 CFG_NON_AGG_RETRY_MAX : retry;
4657 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
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_AGG_RETRY]) {
4663 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4664 retry = retry > CFG_AGG_RETRY_MAX ?
4665 CFG_AGG_RETRY_MAX : retry;
4666
4667 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4668 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4669 CFG_AGG_RETRY_MIN : retry;
4670 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4671 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4672 retry, PDEV_CMD);
4673 }
4674
4675 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4676 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4677 retry = retry > CFG_MGMT_RETRY_MAX ?
4678 CFG_MGMT_RETRY_MAX : retry;
4679 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4680 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4681 retry, PDEV_CMD);
4682 }
4683
4684 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4685 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4686 retry = retry > CFG_CTRL_RETRY_MAX ?
4687 CFG_CTRL_RETRY_MAX : retry;
4688 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4689 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4690 retry, PDEV_CMD);
4691 }
4692
4693 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4694 delay = nla_get_u8(tb[
4695 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4696 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4697 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004698 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004699 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4700 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004701 abs_delay, PDEV_CMD);
4702 }
4703
4704 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4705 abs_delay = nla_get_u8(tb[
4706 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4707 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4708 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4709 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004710 }
4711
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304712 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4713 tx_fail_count = nla_get_u32(
4714 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4715 if (tx_fail_count) {
4716 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4717 adapter->sessionId, tx_fail_count);
4718 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004719 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304720 status);
4721 return -EINVAL;
4722 }
4723 }
4724 }
4725
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304726 if (vendor_ie_present && access_policy_present) {
4727 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4728 access_policy =
4729 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304730 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304731 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304732 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304733
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004734 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304735 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4736 adapter->sessionId, &vendor_ie[0],
4737 access_policy);
4738 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004739 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304740 return -EINVAL;
4741 }
4742 }
4743
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304744 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4745 set_value = nla_get_u8(
4746 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004747 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304748 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4749 }
4750
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304751 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4752 scan_ie_len = nla_len(
4753 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004754 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304755 scan_ie_len, adapter->sessionId,
4756 adapter->device_mode);
4757 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4758 scan_ie = (uint8_t *) nla_data(tb
4759 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304760
4761 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4762 scan_ie_len))
4763 hdd_err("Failed to save default scan IEs");
4764
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304765 if (adapter->device_mode == QDF_STA_MODE) {
4766 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4767 adapter->sessionId, scan_ie,
4768 scan_ie_len);
4769 if (QDF_STATUS_SUCCESS != status)
4770 ret_val = -EPERM;
4771 }
4772 } else
4773 ret_val = -EPERM;
4774 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304775
4776 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4777 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4778 /* if one is specified, both must be specified */
4779 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4780 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4781 hdd_err("Both TX and RX MPDU Aggregation required");
4782 return -EINVAL;
4783 }
4784
4785 request.tx_aggregation_size = nla_get_u8(
4786 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4787 request.rx_aggregation_size = nla_get_u8(
4788 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4789 request.vdev_id = adapter->sessionId;
4790
4791 if (request.tx_aggregation_size >=
4792 CFG_TX_AGGREGATION_SIZE_MIN &&
4793 request.tx_aggregation_size <=
4794 CFG_TX_AGGREGATION_SIZE_MAX &&
4795 request.rx_aggregation_size >=
4796 CFG_RX_AGGREGATION_SIZE_MIN &&
4797 request.rx_aggregation_size <=
4798 CFG_RX_AGGREGATION_SIZE_MAX) {
4799 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4800 if (qdf_status != QDF_STATUS_SUCCESS) {
4801 hdd_err("failed to set aggr sizes err %d",
4802 qdf_status);
4803 ret_val = -EPERM;
4804 }
4805 } else {
4806 hdd_err("TX %d RX %d MPDU aggr size not in range",
4807 request.tx_aggregation_size,
4808 request.rx_aggregation_size);
4809 ret_val = -EINVAL;
4810 }
4811 }
4812
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304813 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4814 uint8_t ignore_assoc_disallowed;
4815
4816 ignore_assoc_disallowed
4817 = nla_get_u8(tb[
4818 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004819 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304820 ignore_assoc_disallowed);
4821 if ((ignore_assoc_disallowed <
4822 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4823 (ignore_assoc_disallowed >
4824 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4825 return -EPERM;
4826
4827 sme_update_session_param(hdd_ctx->hHal,
4828 adapter->sessionId,
4829 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4830 ignore_assoc_disallowed);
4831 }
4832
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004833 return ret_val;
4834}
4835
4836/**
4837 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4838 * vendor command
4839 *
4840 * @wiphy: wiphy device pointer
4841 * @wdev: wireless device pointer
4842 * @data: Vendor command data buffer
4843 * @data_len: Buffer length
4844 *
4845 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4846 *
4847 * Return: EOK or other error codes.
4848 */
4849static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4850 struct wireless_dev *wdev,
4851 const void *data,
4852 int data_len)
4853{
4854 int ret;
4855
4856 cds_ssr_protect(__func__);
4857 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4858 data, data_len);
4859 cds_ssr_unprotect(__func__);
4860
4861 return ret;
4862}
4863
4864static const struct
4865nla_policy
4866qca_wlan_vendor_wifi_logger_start_policy
4867[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4868 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4869 = {.type = NLA_U32 },
4870 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4871 = {.type = NLA_U32 },
4872 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4873 = {.type = NLA_U32 },
4874};
4875
4876/**
4877 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4878 * or disable the collection of packet statistics from the firmware
4879 * @wiphy: WIPHY structure pointer
4880 * @wdev: Wireless device structure pointer
4881 * @data: Pointer to the data received
4882 * @data_len: Length of the data received
4883 *
4884 * This function enables or disables the collection of packet statistics from
4885 * the firmware
4886 *
4887 * Return: 0 on success and errno on failure
4888 */
4889static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4890 struct wireless_dev *wdev,
4891 const void *data,
4892 int data_len)
4893{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304894 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4896 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4897 struct sir_wifi_start_log start_log;
4898
Jeff Johnson1f61b612016-02-12 16:28:33 -08004899 ENTER_DEV(wdev->netdev);
4900
Anurag Chouhan6d760662016-02-20 16:05:43 +05304901 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004902 hdd_err("Command not allowed in FTM mode");
4903 return -EPERM;
4904 }
4905
4906 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304907 if (status)
4908 return status;
4909
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304910 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4911 hdd_err("Driver Modules are closed, can not start logger");
4912 return -EINVAL;
4913 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914
4915 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4916 data, data_len,
4917 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004918 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004919 return -EINVAL;
4920 }
4921
4922 /* Parse and fetch ring id */
4923 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004924 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004925 return -EINVAL;
4926 }
4927 start_log.ring_id = nla_get_u32(
4928 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004929 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004930
4931 /* Parse and fetch verbose level */
4932 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004933 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004934 return -EINVAL;
4935 }
4936 start_log.verbose_level = nla_get_u32(
4937 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004938 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939
4940 /* Parse and fetch flag */
4941 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004942 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004943 return -EINVAL;
4944 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304945 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004946 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004947 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004948
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304949 /* size is buff size which can be set using iwpriv command*/
4950 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05304951 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304952
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004953 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4954
4955 if (start_log.ring_id == RING_ID_WAKELOCK) {
4956 /* Start/stop wakelock events */
4957 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4958 cds_set_wakelock_logging(true);
4959 else
4960 cds_set_wakelock_logging(false);
4961 return 0;
4962 }
4963
4964 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304965 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004966 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004967 status);
4968 return -EINVAL;
4969 }
4970 return 0;
4971}
4972
4973/**
4974 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4975 * or disable the collection of packet statistics from the firmware
4976 * @wiphy: WIPHY structure pointer
4977 * @wdev: Wireless device structure pointer
4978 * @data: Pointer to the data received
4979 * @data_len: Length of the data received
4980 *
4981 * This function is used to enable or disable the collection of packet
4982 * statistics from the firmware
4983 *
4984 * Return: 0 on success and errno on failure
4985 */
4986static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4987 struct wireless_dev *wdev,
4988 const void *data,
4989 int data_len)
4990{
4991 int ret = 0;
4992
4993 cds_ssr_protect(__func__);
4994 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4995 wdev, data, data_len);
4996 cds_ssr_unprotect(__func__);
4997
4998 return ret;
4999}
5000
5001static const struct
5002nla_policy
5003qca_wlan_vendor_wifi_logger_get_ring_data_policy
5004[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5005 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5006 = {.type = NLA_U32 },
5007};
5008
5009/**
5010 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5011 * @wiphy: WIPHY structure pointer
5012 * @wdev: Wireless device structure pointer
5013 * @data: Pointer to the data received
5014 * @data_len: Length of the data received
5015 *
5016 * This function is used to flush or retrieve the per packet statistics from
5017 * the driver
5018 *
5019 * Return: 0 on success and errno on failure
5020 */
5021static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5022 struct wireless_dev *wdev,
5023 const void *data,
5024 int data_len)
5025{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305026 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 uint32_t ring_id;
5028 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5029 struct nlattr *tb
5030 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5031
Jeff Johnson1f61b612016-02-12 16:28:33 -08005032 ENTER_DEV(wdev->netdev);
5033
Anurag Chouhan6d760662016-02-20 16:05:43 +05305034 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005035 hdd_err("Command not allowed in FTM mode");
5036 return -EPERM;
5037 }
5038
5039 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305040 if (status)
5041 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042
5043 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5044 data, data_len,
5045 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005046 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005047 return -EINVAL;
5048 }
5049
5050 /* Parse and fetch ring id */
5051 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005052 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005053 return -EINVAL;
5054 }
5055
5056 ring_id = nla_get_u32(
5057 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5058
5059 if (ring_id == RING_ID_PER_PACKET_STATS) {
5060 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005061 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305062 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5063 /*
5064 * As part of DRIVER ring ID, flush both driver and fw logs.
5065 * For other Ring ID's driver doesn't have any rings to flush
5066 */
5067 hdd_notice("Bug report triggered by framework");
5068
5069 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5070 WLAN_LOG_INDICATOR_FRAMEWORK,
5071 WLAN_LOG_REASON_CODE_UNUSED,
5072 true, false);
5073 if (QDF_STATUS_SUCCESS != status) {
5074 hdd_err("Failed to trigger bug report");
5075 return -EINVAL;
5076 }
5077 } else {
5078 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5079 WLAN_LOG_INDICATOR_FRAMEWORK,
5080 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005081 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005082 return 0;
5083}
5084
5085/**
5086 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5087 * @wiphy: WIPHY structure pointer
5088 * @wdev: Wireless device structure pointer
5089 * @data: Pointer to the data received
5090 * @data_len: Length of the data received
5091 *
5092 * This function is used to flush or retrieve the per packet statistics from
5093 * the driver
5094 *
5095 * Return: 0 on success and errno on failure
5096 */
5097static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5098 struct wireless_dev *wdev,
5099 const void *data,
5100 int data_len)
5101{
5102 int ret = 0;
5103
5104 cds_ssr_protect(__func__);
5105 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5106 wdev, data, data_len);
5107 cds_ssr_unprotect(__func__);
5108
5109 return ret;
5110}
5111
5112#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5113/**
5114 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5115 * @hdd_ctx: HDD context
5116 * @request_id: [input] request id
5117 * @pattern_id: [output] pattern id
5118 *
5119 * This function loops through request id to pattern id array
5120 * if the slot is available, store the request id and return pattern id
5121 * if entry exists, return the pattern id
5122 *
5123 * Return: 0 on success and errno on failure
5124 */
5125static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5126 uint32_t request_id,
5127 uint8_t *pattern_id)
5128{
5129 uint32_t i;
5130
5131 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5132 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5133 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5134 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5135 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5136 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5137 return 0;
5138 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5139 request_id) {
5140 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5141 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5142 return 0;
5143 }
5144 }
5145 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5146 return -EINVAL;
5147}
5148
5149/**
5150 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5151 * @hdd_ctx: HDD context
5152 * @request_id: [input] request id
5153 * @pattern_id: [output] pattern id
5154 *
5155 * This function loops through request id to pattern id array
5156 * reset request id to 0 (slot available again) and
5157 * return pattern id
5158 *
5159 * Return: 0 on success and errno on failure
5160 */
5161static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5162 uint32_t request_id,
5163 uint8_t *pattern_id)
5164{
5165 uint32_t i;
5166
5167 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5168 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5169 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5170 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5171 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5172 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5173 return 0;
5174 }
5175 }
5176 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5177 return -EINVAL;
5178}
5179
5180
5181/*
5182 * define short names for the global vendor params
5183 * used by __wlan_hdd_cfg80211_offloaded_packets()
5184 */
5185#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5186#define PARAM_REQUEST_ID \
5187 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5188#define PARAM_CONTROL \
5189 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5190#define PARAM_IP_PACKET \
5191 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5192#define PARAM_SRC_MAC_ADDR \
5193 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5194#define PARAM_DST_MAC_ADDR \
5195 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5196#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5197
5198/**
5199 * wlan_hdd_add_tx_ptrn() - add tx pattern
5200 * @adapter: adapter pointer
5201 * @hdd_ctx: hdd context
5202 * @tb: nl attributes
5203 *
5204 * This function reads the NL attributes and forms a AddTxPtrn message
5205 * posts it to SME.
5206 *
5207 */
5208static int
5209wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5210 struct nlattr **tb)
5211{
5212 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305213 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005214 uint32_t request_id, ret, len;
5215 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305216 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005217 uint16_t eth_type = htons(ETH_P_IP);
5218
5219 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005220 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005221 return -ENOTSUPP;
5222 }
5223
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305224 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005225 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005226 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005227 return -ENOMEM;
5228 }
5229
5230 /* Parse and fetch request Id */
5231 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005232 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005233 goto fail;
5234 }
5235
5236 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5237 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005238 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 return -EINVAL;
5240 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005241 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005242
5243 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005244 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005245 goto fail;
5246 }
5247 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005248 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005249 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005250 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005251 goto fail;
5252 }
5253
5254 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005255 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256 goto fail;
5257 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005258 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305259 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005260 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005261 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005262
Anurag Chouhanc5548422016-02-24 18:33:27 +05305263 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005264 &adapter->macAddressCurrent)) {
5265 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266 goto fail;
5267 }
5268
5269 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005270 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005271 goto fail;
5272 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305273 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005274 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275 MAC_ADDR_ARRAY(dst_addr.bytes));
5276
5277 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005278 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005279 goto fail;
5280 }
5281 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005282 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005283
5284 if (add_req->ucPtrnSize < 0 ||
5285 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5286 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005287 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005288 add_req->ucPtrnSize);
5289 goto fail;
5290 }
5291
5292 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305293 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305294 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305295 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305296 QDF_MAC_ADDR_SIZE);
5297 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305298 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005299 len += 2;
5300
5301 /*
5302 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5303 * ------------------------------------------------------------
5304 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5305 * ------------------------------------------------------------
5306 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305307 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005308 nla_data(tb[PARAM_IP_PACKET]),
5309 add_req->ucPtrnSize);
5310 add_req->ucPtrnSize += len;
5311
5312 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5313 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005314 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005315 goto fail;
5316 }
5317 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005318 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005319
5320 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305321 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005322 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005323 goto fail;
5324 }
5325
5326 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305327 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 return 0;
5329
5330fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305331 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 return -EINVAL;
5333}
5334
5335/**
5336 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5337 * @adapter: adapter pointer
5338 * @hdd_ctx: hdd context
5339 * @tb: nl attributes
5340 *
5341 * This function reads the NL attributes and forms a DelTxPtrn message
5342 * posts it to SME.
5343 *
5344 */
5345static int
5346wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5347 struct nlattr **tb)
5348{
5349 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305350 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 uint32_t request_id, ret;
5352 uint8_t pattern_id = 0;
5353
5354 /* Parse and fetch request Id */
5355 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005356 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 return -EINVAL;
5358 }
5359 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5360 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005361 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005362 return -EINVAL;
5363 }
5364
5365 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5366 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005367 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005368 return -EINVAL;
5369 }
5370
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305371 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005373 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005374 return -ENOMEM;
5375 }
5376
Anurag Chouhanc5548422016-02-24 18:33:27 +05305377 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005378 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005379 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005380 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005381 request_id, del_req->ucPtrnId);
5382
5383 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305384 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005385 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005386 goto fail;
5387 }
5388
5389 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305390 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005391 return 0;
5392
5393fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305394 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395 return -EINVAL;
5396}
5397
5398
5399/**
5400 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5401 * @wiphy: Pointer to wireless phy
5402 * @wdev: Pointer to wireless device
5403 * @data: Pointer to data
5404 * @data_len: Data length
5405 *
5406 * Return: 0 on success, negative errno on failure
5407 */
5408static int
5409__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5410 struct wireless_dev *wdev,
5411 const void *data,
5412 int data_len)
5413{
5414 struct net_device *dev = wdev->netdev;
5415 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5416 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5417 struct nlattr *tb[PARAM_MAX + 1];
5418 uint8_t control;
5419 int ret;
5420 static const struct nla_policy policy[PARAM_MAX + 1] = {
5421 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5422 [PARAM_CONTROL] = { .type = NLA_U32 },
5423 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305424 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305426 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005427 [PARAM_PERIOD] = { .type = NLA_U32 },
5428 };
5429
Jeff Johnson1f61b612016-02-12 16:28:33 -08005430 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431
Anurag Chouhan6d760662016-02-20 16:05:43 +05305432 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005433 hdd_err("Command not allowed in FTM mode");
5434 return -EPERM;
5435 }
5436
5437 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305438 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440
5441 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005442 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443 return -ENOTSUPP;
5444 }
5445
5446 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005447 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005448 return -EINVAL;
5449 }
5450
5451 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005452 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005453 return -EINVAL;
5454 }
5455 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005456 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005457
5458 if (control == WLAN_START_OFFLOADED_PACKETS)
5459 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005460 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005461 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005462
5463 hdd_err("Invalid control: %d", control);
5464
5465 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005466}
5467
5468/*
5469 * done with short names for the global vendor params
5470 * used by __wlan_hdd_cfg80211_offloaded_packets()
5471 */
5472#undef PARAM_MAX
5473#undef PARAM_REQUEST_ID
5474#undef PARAM_CONTROL
5475#undef PARAM_IP_PACKET
5476#undef PARAM_SRC_MAC_ADDR
5477#undef PARAM_DST_MAC_ADDR
5478#undef PARAM_PERIOD
5479
5480/**
5481 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5482 * @wiphy: wiphy structure pointer
5483 * @wdev: Wireless device structure pointer
5484 * @data: Pointer to the data received
5485 * @data_len: Length of @data
5486 *
5487 * Return: 0 on success; errno on failure
5488 */
5489static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5490 struct wireless_dev *wdev,
5491 const void *data,
5492 int data_len)
5493{
5494 int ret = 0;
5495
5496 cds_ssr_protect(__func__);
5497 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5498 wdev, data, data_len);
5499 cds_ssr_unprotect(__func__);
5500
5501 return ret;
5502}
5503#endif
5504
5505/*
5506 * define short names for the global vendor params
5507 * used by __wlan_hdd_cfg80211_monitor_rssi()
5508 */
5509#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5510#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5511#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5512#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5513#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5514
5515/**
5516 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5517 * @wiphy: Pointer to wireless phy
5518 * @wdev: Pointer to wireless device
5519 * @data: Pointer to data
5520 * @data_len: Data length
5521 *
5522 * Return: 0 on success, negative errno on failure
5523 */
5524static int
5525__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5526 struct wireless_dev *wdev,
5527 const void *data,
5528 int data_len)
5529{
5530 struct net_device *dev = wdev->netdev;
5531 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5532 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5533 struct nlattr *tb[PARAM_MAX + 1];
5534 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305535 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536 int ret;
5537 uint32_t control;
5538 static const struct nla_policy policy[PARAM_MAX + 1] = {
5539 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5540 [PARAM_CONTROL] = { .type = NLA_U32 },
5541 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5542 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5543 };
5544
Jeff Johnson1f61b612016-02-12 16:28:33 -08005545 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305547 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5548 hdd_err("invalid session id: %d", adapter->sessionId);
5549 return -EINVAL;
5550 }
5551
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005552 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305553 if (ret)
5554 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005555
5556 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005557 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005558 return -ENOTSUPP;
5559 }
5560
5561 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005562 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005563 return -EINVAL;
5564 }
5565
5566 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005567 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005568 return -EINVAL;
5569 }
5570
5571 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005572 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005573 return -EINVAL;
5574 }
5575
5576 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5577 req.session_id = adapter->sessionId;
5578 control = nla_get_u32(tb[PARAM_CONTROL]);
5579
5580 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5581 req.control = true;
5582 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005583 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005584 return -EINVAL;
5585 }
5586
5587 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005588 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005589 return -EINVAL;
5590 }
5591
5592 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5593 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5594
5595 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005596 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005597 req.min_rssi, req.max_rssi);
5598 return -EINVAL;
5599 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005600 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005601 req.min_rssi, req.max_rssi);
5602
5603 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5604 req.control = false;
5605 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005606 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005607 return -EINVAL;
5608 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005609 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005610 req.request_id, req.session_id, req.control);
5611
5612 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305613 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005614 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005615 return -EINVAL;
5616 }
5617
5618 return 0;
5619}
5620
5621/*
5622 * done with short names for the global vendor params
5623 * used by __wlan_hdd_cfg80211_monitor_rssi()
5624 */
5625#undef PARAM_MAX
5626#undef PARAM_CONTROL
5627#undef PARAM_REQUEST_ID
5628#undef PARAM_MAX_RSSI
5629#undef PARAM_MIN_RSSI
5630
5631/**
5632 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5633 * @wiphy: wiphy structure pointer
5634 * @wdev: Wireless device structure pointer
5635 * @data: Pointer to the data received
5636 * @data_len: Length of @data
5637 *
5638 * Return: 0 on success; errno on failure
5639 */
5640static int
5641wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5642 const void *data, int data_len)
5643{
5644 int ret;
5645
5646 cds_ssr_protect(__func__);
5647 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5648 cds_ssr_unprotect(__func__);
5649
5650 return ret;
5651}
5652
5653/**
5654 * hdd_rssi_threshold_breached() - rssi breached NL event
5655 * @hddctx: HDD context
5656 * @data: rssi breached event data
5657 *
5658 * This function reads the rssi breached event %data and fill in the skb with
5659 * NL attributes and send up the NL event.
5660 *
5661 * Return: none
5662 */
5663void hdd_rssi_threshold_breached(void *hddctx,
5664 struct rssi_breach_event *data)
5665{
5666 hdd_context_t *hdd_ctx = hddctx;
5667 struct sk_buff *skb;
5668
5669 ENTER();
5670
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305671 if (wlan_hdd_validate_context(hdd_ctx))
5672 return;
5673 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005674 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005675 return;
5676 }
5677
5678 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5679 NULL,
5680 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5681 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5682 GFP_KERNEL);
5683
5684 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005685 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005686 return;
5687 }
5688
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005689 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005690 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005691 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005692 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5693
5694 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5695 data->request_id) ||
5696 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5697 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5698 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5699 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005700 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005701 goto fail;
5702 }
5703
5704 cfg80211_vendor_event(skb, GFP_KERNEL);
5705 return;
5706
5707fail:
5708 kfree_skb(skb);
5709 return;
5710}
5711
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305712static const struct nla_policy
5713ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5714 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5715};
5716
5717/**
5718 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5719 * @wiphy: Pointer to wireless phy
5720 * @wdev: Pointer to wireless device
5721 * @data: Pointer to data
5722 * @data_len: Length of @data
5723 *
5724 * Return: 0 on success, negative errno on failure
5725 */
5726static int
5727__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5728 struct wireless_dev *wdev,
5729 const void *data, int data_len)
5730{
5731 int status;
5732 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5733 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005734 struct net_device *dev = wdev->netdev;
5735 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305736
5737 ENTER_DEV(wdev->netdev);
5738
5739 status = wlan_hdd_validate_context(pHddCtx);
5740 if (0 != status)
5741 return status;
5742 if (!pHddCtx->config->fhostNSOffload) {
5743 hdd_err("ND Offload not supported");
5744 return -EINVAL;
5745 }
5746
5747 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5748 (struct nlattr *)data,
5749 data_len, ns_offload_set_policy)) {
5750 hdd_err("nla_parse failed");
5751 return -EINVAL;
5752 }
5753
5754 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5755 hdd_err("ND Offload flag attribute not present");
5756 return -EINVAL;
5757 }
5758
5759 pHddCtx->ns_offload_enable =
5760 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5761
Dustin Brownd8279d22016-09-07 14:52:57 -07005762 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305763 if (pHddCtx->ns_offload_enable)
5764 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5765 else
5766 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005767
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305768 return 0;
5769}
5770
5771/**
5772 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5773 * @wiphy: pointer to wireless wiphy structure.
5774 * @wdev: pointer to wireless_dev structure.
5775 * @data: Pointer to the data to be passed via vendor interface
5776 * @data_len:Length of the data to be passed
5777 *
5778 * Return: Return the Success or Failure code.
5779 */
5780static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5781 struct wireless_dev *wdev,
5782 const void *data, int data_len)
5783{
5784 int ret;
5785
5786 cds_ssr_protect(__func__);
5787 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5788 cds_ssr_unprotect(__func__);
5789
5790 return ret;
5791}
5792
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005793/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5794 * @wiphy: Pointer to wireless phy
5795 * @wdev: Pointer to wireless device
5796 * @data: Pointer to data
5797 * @data_len: Data length
5798 *
5799 * This function return the preferred frequency list generated by the policy
5800 * manager.
5801 *
5802 * Return: success or failure code
5803 */
5804static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5805 struct wireless_dev
5806 *wdev, const void *data,
5807 int data_len)
5808{
5809 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5810 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305811 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305812 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005813 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305814 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005815 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005816 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5817 struct sk_buff *reply_skb;
5818
Jeff Johnson1f61b612016-02-12 16:28:33 -08005819 ENTER_DEV(wdev->netdev);
5820
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005821 ret = wlan_hdd_validate_context(hdd_ctx);
5822 if (ret)
5823 return -EINVAL;
5824
5825 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5826 data, data_len, NULL)) {
5827 hdd_err("Invalid ATTR");
5828 return -EINVAL;
5829 }
5830
5831 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5832 hdd_err("attr interface type failed");
5833 return -EINVAL;
5834 }
5835
5836 intf_mode = nla_get_u32(tb
5837 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5838
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005839 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840 hdd_err("Invalid interface type");
5841 return -EINVAL;
5842 }
5843
5844 hdd_debug("Userspace requested pref freq list");
5845
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005846 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5847 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305848 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305849 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850 hdd_err("Get pcl failed");
5851 return -EINVAL;
5852 }
5853
5854 /* convert channel number to frequency */
5855 for (i = 0; i < pcl_len; i++) {
5856 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5857 freq_list[i] =
5858 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005859 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005860 else
5861 freq_list[i] =
5862 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005863 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005864 }
5865
5866 /* send the freq_list back to supplicant */
5867 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5868 sizeof(u32) *
5869 pcl_len +
5870 NLMSG_HDRLEN);
5871
5872 if (!reply_skb) {
5873 hdd_err("Allocate reply_skb failed");
5874 return -EINVAL;
5875 }
5876
5877 if (nla_put_u32(reply_skb,
5878 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5879 intf_mode) ||
5880 nla_put(reply_skb,
5881 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5882 sizeof(uint32_t) * pcl_len,
5883 freq_list)) {
5884 hdd_err("nla put fail");
5885 kfree_skb(reply_skb);
5886 return -EINVAL;
5887 }
5888
5889 return cfg80211_vendor_cmd_reply(reply_skb);
5890}
5891
5892/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5893 * @wiphy: Pointer to wireless phy
5894 * @wdev: Pointer to wireless device
5895 * @data: Pointer to data
5896 * @data_len: Data length
5897 *
5898 * This function return the preferred frequency list generated by the policy
5899 * manager.
5900 *
5901 * Return: success or failure code
5902 */
5903static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5904 struct wireless_dev
5905 *wdev, const void *data,
5906 int data_len)
5907{
5908 int ret = 0;
5909
5910 cds_ssr_protect(__func__);
5911 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5912 data, data_len);
5913 cds_ssr_unprotect(__func__);
5914
5915 return ret;
5916}
5917
5918/**
5919 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5920 * @wiphy: Pointer to wireless phy
5921 * @wdev: Pointer to wireless device
5922 * @data: Pointer to data
5923 * @data_len: Data length
5924 *
5925 * Return: 0 on success, negative errno on failure
5926 */
5927static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5928 struct wireless_dev *wdev,
5929 const void *data,
5930 int data_len)
5931{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305932 struct net_device *ndev = wdev->netdev;
5933 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005934 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5935 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005936 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005937 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5938 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005939
Jeff Johnson1f61b612016-02-12 16:28:33 -08005940 ENTER_DEV(ndev);
5941
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005942 ret = wlan_hdd_validate_context(hdd_ctx);
5943 if (ret)
5944 return ret;
5945
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005946 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5947 data, data_len, NULL)) {
5948 hdd_err("Invalid ATTR");
5949 return -EINVAL;
5950 }
5951
5952 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5953 hdd_err("attr interface type failed");
5954 return -EINVAL;
5955 }
5956
5957 intf_mode = nla_get_u32(tb
5958 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5959
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005960 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005961 hdd_err("Invalid interface type");
5962 return -EINVAL;
5963 }
5964
5965 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5966 hdd_err("attr probable freq failed");
5967 return -EINVAL;
5968 }
5969
5970 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5971 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5972
5973 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005974 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005975 channel_hint, HW_MODE_20_MHZ)) {
5976 hdd_err("Set channel hint failed due to concurrency check");
5977 return -EINVAL;
5978 }
5979
Krunal Soni09e55032016-06-07 10:06:55 -07005980 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5981 hdd_warn("Remain On Channel Pending");
5982
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005983 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005984 if (!QDF_IS_STATUS_SUCCESS(ret))
5985 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005987 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
5988 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07005989 SIR_UPDATE_REASON_SET_OPER_CHAN);
5990 if (QDF_STATUS_E_FAILURE == ret) {
5991 /* return in the failure case */
5992 hdd_err("ERROR: connections update failed!!");
5993 return -EINVAL;
5994 }
5995
5996 if (QDF_STATUS_SUCCESS == ret) {
5997 /*
5998 * Success is the only case for which we expect hw mode
5999 * change to take place, hence we need to wait.
6000 * For any other return value it should be a pass
6001 * through
6002 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006003 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006004 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6005 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006006 return -EINVAL;
6007 }
6008
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006009 }
6010
6011 return 0;
6012}
6013
6014/**
6015 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6016 * @wiphy: Pointer to wireless phy
6017 * @wdev: Pointer to wireless device
6018 * @data: Pointer to data
6019 * @data_len: Data length
6020 *
6021 * Return: 0 on success, negative errno on failure
6022 */
6023static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6024 struct wireless_dev *wdev,
6025 const void *data,
6026 int data_len)
6027{
6028 int ret = 0;
6029
6030 cds_ssr_protect(__func__);
6031 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6032 data, data_len);
6033 cds_ssr_unprotect(__func__);
6034
6035 return ret;
6036}
6037
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306038static const struct
6039nla_policy
6040qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6041 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6042};
6043
6044/**
6045 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6046 * @wiphy: WIPHY structure pointer
6047 * @wdev: Wireless device structure pointer
6048 * @data: Pointer to the data received
6049 * @data_len: Length of the data received
6050 *
6051 * This function is used to get link properties like nss, rate flags and
6052 * operating frequency for the active connection with the given peer.
6053 *
6054 * Return: 0 on success and errno on failure
6055 */
6056static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6057 struct wireless_dev *wdev,
6058 const void *data,
6059 int data_len)
6060{
6061 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6062 struct net_device *dev = wdev->netdev;
6063 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6064 hdd_station_ctx_t *hdd_sta_ctx;
6065 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306066 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306067 uint32_t sta_id;
6068 struct sk_buff *reply_skb;
6069 uint32_t rate_flags = 0;
6070 uint8_t nss;
6071 uint8_t final_rate_flags = 0;
6072 uint32_t freq;
6073
Jeff Johnson1f61b612016-02-12 16:28:33 -08006074 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306075
Anurag Chouhan6d760662016-02-20 16:05:43 +05306076 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306077 hdd_err("Command not allowed in FTM mode");
6078 return -EPERM;
6079 }
6080
6081 if (0 != wlan_hdd_validate_context(hdd_ctx))
6082 return -EINVAL;
6083
6084 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6085 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006086 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306087 return -EINVAL;
6088 }
6089
6090 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006091 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306092 adapter->device_mode);
6093 return -EINVAL;
6094 }
6095
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306096 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306097 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006098 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306099 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6100
Krunal Sonib4326f22016-03-10 13:05:51 -08006101 if (adapter->device_mode == QDF_STA_MODE ||
6102 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306103 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6104 if ((hdd_sta_ctx->conn_info.connState !=
6105 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306106 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306107 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006108 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306109 MAC_ADDR_ARRAY(peer_mac));
6110 return -EINVAL;
6111 }
6112
6113 nss = hdd_sta_ctx->conn_info.nss;
6114 freq = cds_chan_to_freq(
6115 hdd_sta_ctx->conn_info.operationChannel);
6116 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006117 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6118 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306119
6120 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6121 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306122 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306123 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306124 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306125 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306126 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306127 break;
6128 }
6129
6130 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006131 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306132 MAC_ADDR_ARRAY(peer_mac));
6133 return -EINVAL;
6134 }
6135
6136 nss = adapter->aStaInfo[sta_id].nss;
6137 freq = cds_chan_to_freq(
6138 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6139 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6140 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006141 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306142 MAC_ADDR_ARRAY(peer_mac));
6143 return -EINVAL;
6144 }
6145
6146 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6147 if (rate_flags & eHAL_TX_RATE_VHT80) {
6148 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006149#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306150 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006151#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306152 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6153 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006154#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306155 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006156#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306157 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6158 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6159 } else if (rate_flags &
6160 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6161 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006162#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306163 if (rate_flags & eHAL_TX_RATE_HT40)
6164 final_rate_flags |=
6165 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006166#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306167 }
6168
6169 if (rate_flags & eHAL_TX_RATE_SGI) {
6170 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6171 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6172 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6173 }
6174 }
6175
6176 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6177 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6178
6179 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006180 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306181 return -EINVAL;
6182 }
6183
6184 if (nla_put_u8(reply_skb,
6185 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6186 nss) ||
6187 nla_put_u8(reply_skb,
6188 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6189 final_rate_flags) ||
6190 nla_put_u32(reply_skb,
6191 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6192 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006193 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306194 kfree_skb(reply_skb);
6195 return -EINVAL;
6196 }
6197
6198 return cfg80211_vendor_cmd_reply(reply_skb);
6199}
6200
6201/**
6202 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6203 * properties.
6204 * @wiphy: WIPHY structure pointer
6205 * @wdev: Wireless device structure pointer
6206 * @data: Pointer to the data received
6207 * @data_len: Length of the data received
6208 *
6209 * This function is used to get link properties like nss, rate flags and
6210 * operating frequency for the active connection with the given peer.
6211 *
6212 * Return: 0 on success and errno on failure
6213 */
6214static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6215 struct wireless_dev *wdev,
6216 const void *data,
6217 int data_len)
6218{
6219 int ret = 0;
6220
6221 cds_ssr_protect(__func__);
6222 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6223 wdev, data, data_len);
6224 cds_ssr_unprotect(__func__);
6225
6226 return ret;
6227}
6228
Peng Xu278d0122015-09-24 16:34:17 -07006229static const struct
6230nla_policy
6231qca_wlan_vendor_ota_test_policy
6232[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6233 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6234};
6235
6236/**
6237 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6238 * @wiphy: Pointer to wireless phy
6239 * @wdev: Pointer to wireless device
6240 * @data: Pointer to data
6241 * @data_len: Data length
6242 *
6243 * Return: 0 on success, negative errno on failure
6244 */
6245static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6246 struct wireless_dev *wdev,
6247 const void *data,
6248 int data_len)
6249{
6250 struct net_device *dev = wdev->netdev;
6251 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6252 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6253 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6254 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6255 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306256 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006257 uint32_t current_roam_state;
6258
Jeff Johnson1f61b612016-02-12 16:28:33 -08006259 ENTER_DEV(dev);
6260
Anurag Chouhan6d760662016-02-20 16:05:43 +05306261 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006262 hdd_err("Command not allowed in FTM mode");
6263 return -EPERM;
6264 }
6265
6266 if (0 != wlan_hdd_validate_context(hdd_ctx))
6267 return -EINVAL;
6268
6269 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6270 data, data_len,
6271 qca_wlan_vendor_ota_test_policy)) {
6272 hdd_err("invalid attr");
6273 return -EINVAL;
6274 }
6275
6276 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6277 hdd_err("attr ota test failed");
6278 return -EINVAL;
6279 }
6280
6281 ota_enable = nla_get_u8(
6282 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6283
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006284 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006285 if (ota_enable != 1) {
6286 hdd_err("Invalid value, only enable test mode is supported!");
6287 return -EINVAL;
6288 }
6289
6290 current_roam_state =
6291 sme_get_current_roam_state(hal, adapter->sessionId);
6292 status = sme_stop_roaming(hal, adapter->sessionId,
6293 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306294 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006295 hdd_err("Enable/Disable roaming failed");
6296 return -EINVAL;
6297 }
6298
6299 status = sme_ps_enable_disable(hal, adapter->sessionId,
6300 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306301 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006302 hdd_err("Enable/Disable power save failed");
6303 /* restore previous roaming setting */
6304 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6305 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6306 status = sme_start_roaming(hal, adapter->sessionId,
6307 eCsrHddIssued);
6308 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6309 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6310 status = sme_stop_roaming(hal, adapter->sessionId,
6311 eCsrHddIssued);
6312
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306313 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006314 hdd_err("Restoring roaming state failed");
6315
6316 return -EINVAL;
6317 }
6318
6319
6320 return 0;
6321}
6322
6323/**
6324 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6325 * @wiphy: Pointer to wireless phy
6326 * @wdev: Pointer to wireless device
6327 * @data: Pointer to data
6328 * @data_len: Data length
6329 *
6330 * Return: 0 on success, negative errno on failure
6331 */
6332static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6333 struct wireless_dev *wdev,
6334 const void *data,
6335 int data_len)
6336{
6337 int ret = 0;
6338
6339 cds_ssr_protect(__func__);
6340 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6341 cds_ssr_unprotect(__func__);
6342
6343 return ret;
6344}
6345
Peng Xu4d67c8f2015-10-16 16:02:26 -07006346/**
6347 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6348 * @wiphy: Pointer to wireless phy
6349 * @wdev: Pointer to wireless device
6350 * @data: Pointer to data
6351 * @data_len: Data length
6352 *
6353 * Return: 0 on success, negative errno on failure
6354 */
6355static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6356 struct wireless_dev *wdev,
6357 const void *data,
6358 int data_len)
6359{
6360 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6361 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006362 hdd_adapter_t *adapter;
6363 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006364 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6365 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006366 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006367
Jeff Johnson1f61b612016-02-12 16:28:33 -08006368 ENTER_DEV(dev);
6369
Peng Xu4d67c8f2015-10-16 16:02:26 -07006370 ret = wlan_hdd_validate_context(hdd_ctx);
6371 if (ret)
6372 return ret;
6373
6374 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6375
6376 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6377 data, data_len, NULL)) {
6378 hdd_err("Invalid ATTR");
6379 return -EINVAL;
6380 }
6381
6382 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6383 hdd_err("attr tx power scale failed");
6384 return -EINVAL;
6385 }
6386
6387 scale_value = nla_get_u8(tb
6388 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6389
6390 if (scale_value > MAX_TXPOWER_SCALE) {
6391 hdd_err("Invalid tx power scale level");
6392 return -EINVAL;
6393 }
6394
Peng Xu62c8c432016-05-09 15:23:02 -07006395 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006396
Peng Xu62c8c432016-05-09 15:23:02 -07006397 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006398 hdd_err("Set tx power scale failed");
6399 return -EINVAL;
6400 }
6401
6402 return 0;
6403}
6404
6405/**
6406 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6407 * @wiphy: Pointer to wireless phy
6408 * @wdev: Pointer to wireless device
6409 * @data: Pointer to data
6410 * @data_len: Data length
6411 *
6412 * Return: 0 on success, negative errno on failure
6413 */
6414static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6415 struct wireless_dev *wdev,
6416 const void *data,
6417 int data_len)
6418{
Peng Xu62c8c432016-05-09 15:23:02 -07006419 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006420
6421 cds_ssr_protect(__func__);
6422 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6423 data, data_len);
6424 cds_ssr_unprotect(__func__);
6425
6426 return ret;
6427}
6428
6429/**
6430 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6431 * @wiphy: Pointer to wireless phy
6432 * @wdev: Pointer to wireless device
6433 * @data: Pointer to data
6434 * @data_len: Data length
6435 *
6436 * Return: 0 on success, negative errno on failure
6437 */
6438static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6439 struct wireless_dev *wdev,
6440 const void *data,
6441 int data_len)
6442{
6443 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6444 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006445 hdd_adapter_t *adapter;
6446 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006447 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6448 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006449 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006450
Jeff Johnson1f61b612016-02-12 16:28:33 -08006451 ENTER_DEV(dev);
6452
Peng Xu4d67c8f2015-10-16 16:02:26 -07006453 ret = wlan_hdd_validate_context(hdd_ctx);
6454 if (ret)
6455 return ret;
6456
6457 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6458
6459 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6460 data, data_len, NULL)) {
6461 hdd_err("Invalid ATTR");
6462 return -EINVAL;
6463 }
6464
6465 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6466 hdd_err("attr tx power decrease db value failed");
6467 return -EINVAL;
6468 }
6469
6470 scale_value = nla_get_u8(tb
6471 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6472
Peng Xu62c8c432016-05-09 15:23:02 -07006473 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6474 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006475
Peng Xu62c8c432016-05-09 15:23:02 -07006476 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006477 hdd_err("Set tx power decrease db failed");
6478 return -EINVAL;
6479 }
6480
6481 return 0;
6482}
6483
6484/**
6485 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6486 * @wiphy: Pointer to wireless phy
6487 * @wdev: Pointer to wireless device
6488 * @data: Pointer to data
6489 * @data_len: Data length
6490 *
6491 * Return: 0 on success, negative errno on failure
6492 */
6493static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6494 struct wireless_dev *wdev,
6495 const void *data,
6496 int data_len)
6497{
Peng Xu62c8c432016-05-09 15:23:02 -07006498 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006499
6500 cds_ssr_protect(__func__);
6501 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6502 data, data_len);
6503 cds_ssr_unprotect(__func__);
6504
6505 return ret;
6506}
Peng Xu8fdaa492016-06-22 10:20:47 -07006507
6508/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306509 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6510 * @wiphy: Pointer to wireless phy
6511 * @wdev: Pointer to wireless device
6512 * @data: Pointer to data
6513 * @data_len: Data length
6514 *
6515 * Processes the conditional channel switch request and invokes the helper
6516 * APIs to process the channel switch request.
6517 *
6518 * Return: 0 on success, negative errno on failure
6519 */
6520static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6521 struct wireless_dev *wdev,
6522 const void *data,
6523 int data_len)
6524{
6525 int ret;
6526 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6527 struct net_device *dev = wdev->netdev;
6528 hdd_adapter_t *adapter;
6529 struct nlattr
6530 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6531 uint32_t freq_len, i;
6532 uint32_t *freq;
6533 uint8_t chans[QDF_MAX_NUM_CHAN];
6534
6535 ENTER_DEV(dev);
6536
6537 ret = wlan_hdd_validate_context(hdd_ctx);
6538 if (ret)
6539 return ret;
6540
6541 if (!hdd_ctx->config->enableDFSMasterCap) {
6542 hdd_err("DFS master capability is not present in the driver");
6543 return -EINVAL;
6544 }
6545
6546 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6547 hdd_err("Command not allowed in FTM mode");
6548 return -EPERM;
6549 }
6550
6551 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6552 if (adapter->device_mode != QDF_SAP_MODE) {
6553 hdd_err("Invalid device mode %d", adapter->device_mode);
6554 return -EINVAL;
6555 }
6556
6557 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6558 data, data_len, NULL)) {
6559 hdd_err("Invalid ATTR");
6560 return -EINVAL;
6561 }
6562
6563 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6564 hdd_err("Frequency list is missing");
6565 return -EINVAL;
6566 }
6567
6568 freq_len = nla_len(
6569 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6570 sizeof(uint32_t);
6571
6572 if (freq_len > QDF_MAX_NUM_CHAN) {
6573 hdd_err("insufficient space to hold channels");
6574 return -ENOMEM;
6575 }
6576
6577 hdd_debug("freq_len=%d", freq_len);
6578
6579 freq = nla_data(
6580 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6581
6582
6583 for (i = 0; i < freq_len; i++) {
6584 if (freq[i] == 0)
6585 chans[i] = 0;
6586 else
6587 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6588
6589 hdd_debug("freq[%d]=%d", i, freq[i]);
6590 }
6591
6592 /*
6593 * The input frequency list from user space is designed to be a
6594 * priority based frequency list. This is only to accommodate any
6595 * future request. But, current requirement is only to perform CAC
6596 * on a single channel. So, the first entry from the list is picked.
6597 *
6598 * If channel is zero, any channel in the available outdoor regulatory
6599 * domain will be selected.
6600 */
6601 ret = wlan_hdd_request_pre_cac(chans[0]);
6602 if (ret) {
6603 hdd_err("pre cac request failed with reason:%d", ret);
6604 return ret;
6605 }
6606
6607 return 0;
6608}
6609
6610/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006611 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6612 * @wiphy: Pointer to wireless phy
6613 * @wdev: Pointer to wireless device
6614 * @data: Pointer to data
6615 * @data_len: Data length
6616 *
6617 * This function is to process the p2p listen offload start vendor
6618 * command. It parses the input parameters and invoke WMA API to
6619 * send the command to firmware.
6620 *
6621 * Return: 0 on success, negative errno on failure
6622 */
6623static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6624 struct wireless_dev *wdev,
6625 const void *data,
6626 int data_len)
6627{
6628 int ret;
6629 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6630 struct net_device *dev = wdev->netdev;
6631 hdd_adapter_t *adapter;
6632 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6633 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006634
6635 ENTER_DEV(dev);
6636
6637 ret = wlan_hdd_validate_context(hdd_ctx);
6638 if (ret)
6639 return ret;
6640
6641 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6642 hdd_err("Command not allowed in FTM mode");
6643 return -EPERM;
6644 }
6645
6646 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6647 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6648 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6649 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6650 hdd_err("Invalid device mode %d", adapter->device_mode);
6651 return -EINVAL;
6652 }
6653
6654 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6655 data, data_len, NULL)) {
6656 hdd_err("Invalid ATTR");
6657 return -EINVAL;
6658 }
6659
6660 memset(&params, 0, sizeof(params));
6661
6662 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6663 params.ctl_flags = 1; /* set to default value */
6664 else
6665 params.ctl_flags = nla_get_u32(tb
6666 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6667
6668 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6669 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6670 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6671 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6672 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6673 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6674 hdd_err("Attribute parsing failed");
6675 return -EINVAL;
6676 }
6677
6678 params.vdev_id = adapter->sessionId;
6679 params.freq = nla_get_u32(tb
6680 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6681 if ((params.freq != 2412) && (params.freq != 2437) &&
6682 (params.freq != 2462)) {
6683 hdd_err("Invalid listening channel: %d", params.freq);
6684 return -EINVAL;
6685 }
6686
6687 params.period = nla_get_u32(tb
6688 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6689 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6690 hdd_err("Invalid period: %d", params.period);
6691 return -EINVAL;
6692 }
6693
6694 params.interval = nla_get_u32(tb
6695 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6696 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6697 hdd_err("Invalid interval: %d", params.interval);
6698 return -EINVAL;
6699 }
6700
6701 params.count = nla_get_u32(tb
6702 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006703 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006704 hdd_err("Invalid count: %d", params.count);
6705 return -EINVAL;
6706 }
6707
6708 params.device_types = nla_data(tb
6709 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6710 if (params.device_types == NULL) {
6711 hdd_err("Invalid device types");
6712 return -EINVAL;
6713 }
6714
6715 params.dev_types_len = nla_len(tb
6716 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6717 if (params.dev_types_len < 8) {
6718 hdd_err("Invalid device type length: %d", params.dev_types_len);
6719 return -EINVAL;
6720 }
6721
6722 params.probe_resp_tmplt = nla_data(tb
6723 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6724 if (params.probe_resp_tmplt == NULL) {
6725 hdd_err("Invalid probe response template");
6726 return -EINVAL;
6727 }
6728
6729 params.probe_resp_len = nla_len(tb
6730 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6731 if (params.probe_resp_len == 0) {
6732 hdd_err("Invalid probe resp template length: %d",
6733 params.probe_resp_len);
6734 return -EINVAL;
6735 }
6736
6737 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6738 params.freq, params.period, params.interval, params.count);
6739
Wu Gao9a704f42017-03-10 18:42:11 +08006740 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006741}
6742
6743
6744/**
6745 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6746 * @wiphy: Pointer to wireless phy
6747 * @wdev: Pointer to wireless device
6748 * @data: Pointer to data
6749 * @data_len: Data length
6750 *
6751 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6752 * to process p2p listen offload start vendor command.
6753 *
6754 * Return: 0 on success, negative errno on failure
6755 */
6756static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6757 struct wireless_dev *wdev,
6758 const void *data,
6759 int data_len)
6760{
6761 int ret = 0;
6762
6763 cds_ssr_protect(__func__);
6764 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6765 data, data_len);
6766 cds_ssr_unprotect(__func__);
6767
6768 return ret;
6769}
6770
6771/**
6772 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6773 * @wiphy: Pointer to wireless phy
6774 * @wdev: Pointer to wireless device
6775 * @data: Pointer to data
6776 * @data_len: Data length
6777 *
6778 * This function is to process the p2p listen offload stop vendor
6779 * command. It invokes WMA API to send command to firmware.
6780 *
6781 * Return: 0 on success, negative errno on failure
6782 */
6783static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6784 struct wireless_dev *wdev,
6785 const void *data,
6786 int data_len)
6787{
Peng Xu8fdaa492016-06-22 10:20:47 -07006788 hdd_adapter_t *adapter;
6789 struct net_device *dev = wdev->netdev;
6790
6791 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6792 hdd_err("Command not allowed in FTM mode");
6793 return -EPERM;
6794 }
6795
6796 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6797 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6798 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6799 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6800 hdd_err("Invalid device mode");
6801 return -EINVAL;
6802 }
6803
Wu Gao9a704f42017-03-10 18:42:11 +08006804 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006805}
6806
6807/**
6808 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6809 * @wiphy: Pointer to wireless phy
6810 * @wdev: Pointer to wireless device
6811 * @data: Pointer to data
6812 * @data_len: Data length
6813 *
6814 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6815 * to process p2p listen offload stop vendor command.
6816 *
6817 * Return: 0 on success, negative errno on failure
6818 */
6819static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6820 struct wireless_dev *wdev,
6821 const void *data,
6822 int data_len)
6823{
6824 int ret = 0;
6825
6826 cds_ssr_protect(__func__);
6827 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6828 data, data_len);
6829 cds_ssr_unprotect(__func__);
6830
6831 return ret;
6832}
6833
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306834/**
6835 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6836 * @wiphy: Pointer to wireless phy
6837 * @wdev: Pointer to wireless device
6838 * @data: Pointer to data
6839 * @data_len: Data length
6840 *
6841 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6842 * to process the conditional channel switch request.
6843 *
6844 * Return: 0 on success, negative errno on failure
6845 */
6846static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6847 struct wireless_dev *wdev,
6848 const void *data,
6849 int data_len)
6850{
6851 int ret;
6852
6853 cds_ssr_protect(__func__);
6854 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6855 data, data_len);
6856 cds_ssr_unprotect(__func__);
6857
6858 return ret;
6859}
6860
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306861/*
6862 * define short names for the global vendor params
6863 * used by __wlan_hdd_cfg80211_bpf_offload()
6864 */
6865#define BPF_INVALID \
6866 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6867#define BPF_SET_RESET \
6868 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6869#define BPF_VERSION \
6870 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6871#define BPF_FILTER_ID \
6872 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6873#define BPF_PACKET_SIZE \
6874 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6875#define BPF_CURRENT_OFFSET \
6876 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6877#define BPF_PROGRAM \
6878 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6879#define BPF_MAX \
6880 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006881
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306882static const struct nla_policy
6883wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6884 [BPF_SET_RESET] = {.type = NLA_U32},
6885 [BPF_VERSION] = {.type = NLA_U32},
6886 [BPF_FILTER_ID] = {.type = NLA_U32},
6887 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6888 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6889 [BPF_PROGRAM] = {.type = NLA_U8},
6890};
6891
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006892struct bpf_offload_priv {
6893 struct sir_bpf_get_offload bpf_get_offload;
6894};
6895
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306896/**
6897 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006898 * @context: opaque context originally passed to SME. HDD always passes
6899 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306900 * @bpf_get_offload: struct for get offload
6901 *
6902 * This function receives the response/data from the lower layer and
6903 * checks to see if the thread is still waiting then post the results to
6904 * upper layer, if the request has timed out then ignore.
6905 *
6906 * Return: None
6907 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006908static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006909 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306910{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006911 struct hdd_request *request;
6912 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306913
6914 ENTER();
6915
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006916 request = hdd_request_get(context);
6917 if (!request) {
6918 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306919 return;
6920 }
6921
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006922 priv = hdd_request_priv(request);
6923 priv->bpf_get_offload = *data;
6924 hdd_request_complete(request);
6925 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306926}
6927
6928/**
6929 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6930 * @hdd_context: hdd_context
6931 * @bpf_get_offload: struct for get offload
6932 *
6933 * Return: 0 on success, error number otherwise.
6934 */
6935static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6936 struct sir_bpf_get_offload *bpf_get_offload)
6937{
6938 struct sk_buff *skb;
6939 uint32_t nl_buf_len;
6940
6941 ENTER();
6942
6943 nl_buf_len = NLMSG_HDRLEN;
6944 nl_buf_len +=
6945 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6946 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6947
6948 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6949 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006950 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306951 return -ENOMEM;
6952 }
6953
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006954 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306955 bpf_get_offload->bpf_version,
6956 bpf_get_offload->max_bytes_for_bpf_inst);
6957
6958 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6959 bpf_get_offload->max_bytes_for_bpf_inst) ||
6960 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006961 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306962 goto nla_put_failure;
6963 }
6964
6965 cfg80211_vendor_cmd_reply(skb);
6966 EXIT();
6967 return 0;
6968
6969nla_put_failure:
6970 kfree_skb(skb);
6971 return -EINVAL;
6972}
6973
6974/**
6975 * hdd_get_bpf_offload - Get BPF offload Capabilities
6976 * @hdd_ctx: Hdd context
6977 *
6978 * Return: 0 on success, errno on failure
6979 */
6980static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6981{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306982 QDF_STATUS status;
6983 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006984 void *cookie;
6985 struct hdd_request *request;
6986 struct bpf_offload_priv *priv;
6987 static const struct hdd_request_params params = {
6988 .priv_size = sizeof(*priv),
6989 .timeout_ms = WLAN_WAIT_TIME_BPF,
6990 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306991
6992 ENTER();
6993
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006994 request = hdd_request_alloc(&params);
6995 if (!request) {
6996 hdd_err("Unable to allocate request");
6997 return -EINVAL;
6998 }
6999 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007001 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7002 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007003 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307004 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007005 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007006 ret = qdf_status_to_os_return(status);
7007 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307008 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007009 ret = hdd_request_wait_for_response(request);
7010 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007011 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007012 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307013 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007014 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307015 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007016 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307017 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007018 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307019
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007020cleanup:
7021 /*
7022 * either we never sent a request to SME, we sent a request to
7023 * SME and timed out, or we sent a request to SME, received a
7024 * response from SME, and posted the response to userspace.
7025 * regardless we are done with the request.
7026 */
7027 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307028 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007029
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307030 return ret;
7031}
7032
7033/**
7034 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7035 * @hdd_ctx: Hdd context
7036 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307037 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307038 *
7039 * Return: 0 on success; errno on failure
7040 */
7041static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7042 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307043 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307044{
7045 struct sir_bpf_set_offload *bpf_set_offload;
7046 QDF_STATUS status;
7047 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307048 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307049
7050 ENTER();
7051
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307052 if (adapter->device_mode == QDF_STA_MODE ||
7053 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7054 if (!hdd_conn_is_connected(
7055 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7056 hdd_err("Not in Connected state!");
7057 return -ENOTSUPP;
7058 }
7059 }
7060
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307061 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7062 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007063 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307064 return -ENOMEM;
7065 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307066
7067 /* Parse and fetch bpf packet size */
7068 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007069 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307070 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307071 goto fail;
7072 }
7073 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7074
7075 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007076 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307077 goto post_sme;
7078 }
7079
7080 /* Parse and fetch bpf program */
7081 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007082 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307083 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307084 goto fail;
7085 }
7086
7087 prog_len = nla_len(tb[BPF_PROGRAM]);
7088 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307089
7090 if (bpf_set_offload->program == NULL) {
7091 hdd_err("qdf_mem_malloc failed for bpf offload program");
7092 ret = -ENOMEM;
7093 goto fail;
7094 }
7095
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307096 bpf_set_offload->current_length = prog_len;
7097 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307098 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307099
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007100 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007101 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307102 bpf_set_offload->program, prog_len);
7103
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307104 /* Parse and fetch filter Id */
7105 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007106 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307107 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307108 goto fail;
7109 }
7110 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7111
7112 /* Parse and fetch current offset */
7113 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007114 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307115 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307116 goto fail;
7117 }
7118 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7119
7120post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007121 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 +05307122 bpf_set_offload->session_id,
7123 bpf_set_offload->version,
7124 bpf_set_offload->filter_id,
7125 bpf_set_offload->total_length,
7126 bpf_set_offload->current_length,
7127 bpf_set_offload->current_offset);
7128
7129 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7130 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007131 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307132 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307133 goto fail;
7134 }
7135 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307136
7137fail:
7138 if (bpf_set_offload->current_length)
7139 qdf_mem_free(bpf_set_offload->program);
7140 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307141 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307142}
7143
7144/**
7145 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7146 * @wiphy: wiphy structure pointer
7147 * @wdev: Wireless device structure pointer
7148 * @data: Pointer to the data received
7149 * @data_len: Length of @data
7150 *
7151 * Return: 0 on success; errno on failure
7152 */
7153static int
7154__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7155 struct wireless_dev *wdev,
7156 const void *data, int data_len)
7157{
7158 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7159 struct net_device *dev = wdev->netdev;
7160 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7161 struct nlattr *tb[BPF_MAX + 1];
7162 int ret_val, packet_filter_subcmd;
7163
7164 ENTER();
7165
7166 ret_val = wlan_hdd_validate_context(hdd_ctx);
7167 if (ret_val)
7168 return ret_val;
7169
7170 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007171 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307172 return -EINVAL;
7173 }
7174
7175 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007176 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307177 return -ENOTSUPP;
7178 }
7179
7180 if (nla_parse(tb, BPF_MAX, data, data_len,
7181 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007182 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307183 return -EINVAL;
7184 }
7185
7186 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007187 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307188 return -EINVAL;
7189 }
7190
7191 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7192
7193 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7194 return hdd_get_bpf_offload(hdd_ctx);
7195 else
7196 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307197 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307198}
7199
7200/**
7201 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7202 * @wiphy: wiphy structure pointer
7203 * @wdev: Wireless device structure pointer
7204 * @data: Pointer to the data received
7205 * @data_len: Length of @data
7206 *
7207 * Return: 0 on success; errno on failure
7208 */
7209
7210static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7211 struct wireless_dev *wdev,
7212 const void *data, int data_len)
7213{
7214 int ret;
7215
7216 cds_ssr_protect(__func__);
7217 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7218 cds_ssr_unprotect(__func__);
7219
7220 return ret;
7221}
7222
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307223/**
7224 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7225 * @pre_cac_adapter: AP adapter used for pre cac
7226 * @status: Status (true or false)
7227 * @handle: Global handle
7228 *
7229 * Sets the status of pre cac i.e., whether the pre cac is active or not
7230 *
7231 * Return: Zero on success, non-zero on failure
7232 */
7233static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7234 bool status, tHalHandle handle)
7235{
7236 QDF_STATUS ret;
7237
7238 ret = wlan_sap_set_pre_cac_status(
7239 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7240 if (QDF_IS_STATUS_ERROR(ret))
7241 return -EINVAL;
7242
7243 return 0;
7244}
7245
7246/**
7247 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7248 * @ap_adapter: AP adapter
7249 * @chan_before_pre_cac: Channel
7250 *
7251 * Saves the channel which the AP was beaconing on before moving to the pre
7252 * cac channel. If radar is detected on the pre cac channel, this saved
7253 * channel will be used for AP operations.
7254 *
7255 * Return: Zero on success, non-zero on failure
7256 */
7257static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7258 uint8_t chan_before_pre_cac)
7259{
7260 QDF_STATUS ret;
7261
7262 ret = wlan_sap_set_chan_before_pre_cac(
7263 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7264 if (QDF_IS_STATUS_ERROR(ret))
7265 return -EINVAL;
7266
7267 return 0;
7268}
7269
7270/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307271 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7272 * are in nol list from provided channel list
7273 * @adapter: AP adapter
7274 * @channel_count: channel count
7275 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307276 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307277 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307278 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307279static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7280 uint32_t *channel_count,
7281 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307282{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307283 uint8_t i, j;
7284 uint32_t nol_len = 0;
7285 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7286 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7287 uint32_t chan_count;
7288 bool found;
7289 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307290
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307291 if (!hdd_ctx) {
7292 hdd_err("hdd ctx not found");
7293 *channel_count = 0;
7294 return;
7295 }
7296
7297 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7298 hdd_err("invalid channel count %d", *channel_count);
7299 return;
7300 }
7301
7302 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7303 if (nol_len == 0)
7304 return;
7305
7306 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7307 chan_count = *channel_count;
7308 qdf_mem_zero(channel_list, chan_count);
7309 *channel_count = 0;
7310
7311 for (i = 0 ; i < chan_count; i++) {
7312 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7313 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7314 continue;
7315 found = false;
7316 for (j = 0; j < nol_len; j++) {
7317 if (tmp_chan_list[i] == nol[j]) {
7318 found = true;
7319 hdd_notice("skipped channel %d due to nol",
7320 nol[j]);
7321 break;
7322 }
7323 }
7324 if (!found) {
7325 channel_list[*channel_count] = tmp_chan_list[i];
7326 *channel_count = *channel_count + 1;
7327 }
7328 }
7329}
7330
7331int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7332 uint32_t *channel_count,
7333 uint8_t *channel_list)
7334{
7335 tsap_Config_t *sap_config;
7336
7337 sap_config = &adapter->sessionCtx.ap.sapConfig;
7338
7339 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7340 sap_config->acs_cfg.ch_list_count);
7341 *channel_count = sap_config->acs_cfg.ch_list_count;
7342 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7343
7344 if (*channel_count == 0) {
7345 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307346 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307347 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307348
7349 return 0;
7350}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307351
7352/**
7353 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7354 * @hdd_ctx: HDD context
7355 * @ap_adapter: AP adapter
7356 * @channel: Channel requested by userspace
7357 * @pre_cac_chan: Pointer to the pre CAC channel
7358 *
7359 * Validates the channel provided by userspace. If user provided channel 0,
7360 * a valid outdoor channel must be selected from the regulatory channel.
7361 *
7362 * Return: Zero on success and non zero value on error
7363 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007364static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7365 hdd_adapter_t *ap_adapter,
7366 uint8_t channel,
7367 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307368{
7369 uint32_t i, j;
7370 QDF_STATUS status;
7371 int ret;
7372 uint8_t nol[QDF_MAX_NUM_CHAN];
7373 uint32_t nol_len = 0, weight_len = 0;
7374 bool found;
7375 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7376 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7377 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7378
7379 if (0 == channel) {
7380 /* Channel is not obtained from PCL because PCL may not have
7381 * the entire channel list. For example: if SAP is up on
7382 * channel 6 and PCL is queried for the next SAP interface,
7383 * if SCC is preferred, the PCL will contain only the channel
7384 * 6. But, we are in need of a DFS channel. So, going with the
7385 * first channel from the valid channel list.
7386 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007387 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7388 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307389 if (QDF_IS_STATUS_ERROR(status)) {
7390 hdd_err("Failed to get channel list");
7391 return -EINVAL;
7392 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007393 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307394 pcl_weights, weight_len);
7395 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7396 for (i = 0; i < len; i++) {
7397 found = false;
7398 for (j = 0; j < nol_len; j++) {
7399 if (channel_list[i] == nol[j]) {
7400 found = true;
7401 break;
7402 }
7403 }
7404 if (found)
7405 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007406 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7407 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307408 *pre_cac_chan = channel_list[i];
7409 break;
7410 }
7411 }
7412 if (*pre_cac_chan == 0) {
7413 hdd_err("unable to find outdoor channel");
7414 return -EINVAL;
7415 }
7416 } else {
7417 /* Only when driver selects a channel, check is done for
7418 * unnsafe and NOL channels. When user provides a fixed channel
7419 * the user is expected to take care of this.
7420 */
7421 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007422 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307423 hdd_err("Invalid channel for pre cac:%d", channel);
7424 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307425 }
Jeff Johnson68755312017-02-10 11:46:55 -08007426
7427 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307428 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007429 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307430 return 0;
7431}
7432
7433/**
7434 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7435 * @channel: Channel option provided by userspace
7436 *
7437 * Sets the driver to the required hardware mode and start an adapater for
7438 * pre CAC which will mimic an AP.
7439 *
7440 * Return: Zero on success, non-zero value on error
7441 */
7442int wlan_hdd_request_pre_cac(uint8_t channel)
7443{
Krunal Sonib37bb352016-12-20 14:12:21 -08007444 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307445 hdd_context_t *hdd_ctx;
7446 int ret;
7447 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7448 hdd_ap_ctx_t *hdd_ap_ctx;
7449 QDF_STATUS status;
7450 struct wiphy *wiphy;
7451 struct net_device *dev;
7452 struct cfg80211_chan_def chandef;
7453 enum nl80211_channel_type channel_type;
7454 uint32_t freq;
7455 struct ieee80211_channel *chan;
7456 tHalHandle handle;
7457 bool val;
7458
7459 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7460 if (0 != wlan_hdd_validate_context(hdd_ctx))
7461 return -EINVAL;
7462
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007463 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307464 hdd_err("pre cac not allowed in concurrency");
7465 return -EINVAL;
7466 }
7467
7468 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7469 if (!ap_adapter) {
7470 hdd_err("unable to get SAP adapter");
7471 return -EINVAL;
7472 }
7473
7474 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7475 if (!handle) {
7476 hdd_err("Invalid handle");
7477 return -EINVAL;
7478 }
7479
7480 val = wlan_sap_is_pre_cac_active(handle);
7481 if (val) {
7482 hdd_err("pre cac is already in progress");
7483 return -EINVAL;
7484 }
7485
7486 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7487 if (!hdd_ap_ctx) {
7488 hdd_err("SAP context is NULL");
7489 return -EINVAL;
7490 }
7491
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007492 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7493 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307494 hdd_err("SAP is already on DFS channel:%d",
7495 hdd_ap_ctx->operatingChannel);
7496 return -EINVAL;
7497 }
7498
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007499 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307500 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7501 hdd_ap_ctx->operatingChannel);
7502 return -EINVAL;
7503 }
7504
Krunal Sonib37bb352016-12-20 14:12:21 -08007505 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7506 if (!mac_addr) {
7507 hdd_err("can't add virtual intf: Not getting valid mac addr");
7508 return -EINVAL;
7509 }
7510
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007511 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307512
7513 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7514 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007515 if (ret != 0) {
7516 hdd_err("can't validate pre-cac channel");
7517 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307518 }
7519
7520 hdd_debug("starting pre cac SAP adapter");
7521
7522 /* Starting a SAP adapter:
7523 * Instead of opening an adapter, we could just do a SME open session
7524 * for AP type. But, start BSS would still need an adapter.
7525 * So, this option is not taken.
7526 *
7527 * hdd open adapter is going to register this precac interface with
7528 * user space. This interface though exposed to user space will be in
7529 * DOWN state. Consideration was done to avoid this registration to the
7530 * user space. But, as part of SAP operations multiple events are sent
7531 * to user space. Some of these events received from unregistered
7532 * interface was causing crashes. So, retaining the registration.
7533 *
7534 * So, this interface would remain registered and will remain in DOWN
7535 * state for the CAC duration. We will add notes in the feature
7536 * announcement to not use this temporary interface for any activity
7537 * from user space.
7538 */
7539 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007540 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307541 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307542 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007543 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307544 }
7545
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307546 /*
7547 * This interface is internally created by the driver. So, no interface
7548 * up comes for this interface from user space and hence starting
7549 * the adapter internally.
7550 */
7551 if (hdd_start_adapter(pre_cac_adapter)) {
7552 hdd_err("error starting the pre cac adapter");
7553 goto close_pre_cac_adapter;
7554 }
7555
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307556 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7557
7558 wiphy = hdd_ctx->wiphy;
7559 dev = pre_cac_adapter->dev;
7560
7561 /* Since this is only a dummy interface lets us use the IEs from the
7562 * other active SAP interface. In regular scenarios, these IEs would
7563 * come from the user space entity
7564 */
7565 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7566 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7567 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7568 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307569 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307570 }
7571 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7572 ap_adapter->sessionCtx.ap.beacon,
7573 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7574 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7575 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7576 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7577 ap_adapter->sessionCtx.ap.sapConfig.authType;
7578
7579 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7580 * to operate on the same bandwidth as that of the 2.4GHz operations.
7581 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7582 */
7583 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7584 case CH_WIDTH_20MHZ:
7585 channel_type = NL80211_CHAN_HT20;
7586 break;
7587 case CH_WIDTH_40MHZ:
7588 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7589 ap_adapter->sessionCtx.ap.sapConfig.channel)
7590 channel_type = NL80211_CHAN_HT40PLUS;
7591 else
7592 channel_type = NL80211_CHAN_HT40MINUS;
7593 break;
7594 default:
7595 channel_type = NL80211_CHAN_NO_HT;
7596 break;
7597 }
7598
7599 freq = cds_chan_to_freq(pre_cac_chan);
7600 chan = __ieee80211_get_channel(wiphy, freq);
7601 if (!chan) {
7602 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307603 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307604 }
7605
7606 cfg80211_chandef_create(&chandef, chan, channel_type);
7607
7608 hdd_debug("orig width:%d channel_type:%d freq:%d",
7609 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7610 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007611 /*
7612 * Doing update after opening and starting pre-cac adapter will make
7613 * sure that driver won't do hardware mode change if there are any
7614 * initial hick-ups or issues in pre-cac adapter's configuration.
7615 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7616 * connection update should result in DBS mode
7617 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007618 status = policy_mgr_update_and_wait_for_connection_update(
7619 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007620 ap_adapter->sessionId,
7621 pre_cac_chan,
7622 SIR_UPDATE_REASON_PRE_CAC);
7623 if (QDF_IS_STATUS_ERROR(status)) {
7624 hdd_err("error in moving to DBS mode");
7625 goto stop_close_pre_cac_adapter;
7626 }
7627
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307628
7629 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7630 if (0 != ret) {
7631 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307632 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307633 }
7634
7635 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7636 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007637 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307638 if (QDF_IS_STATUS_ERROR(status)) {
7639 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307640 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307641 }
7642
7643 /*
7644 * The pre cac status is set here. But, it would not be reset explicitly
7645 * anywhere, since after the pre cac success/failure, the pre cac
7646 * adapter itself would be removed.
7647 */
7648 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7649 if (0 != ret) {
7650 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307651 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307652 }
7653
7654 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7655 hdd_ap_ctx->operatingChannel);
7656 if (0 != ret) {
7657 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307658 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307659 }
7660
7661 ap_adapter->pre_cac_chan = pre_cac_chan;
7662
7663 return 0;
7664
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307665stop_close_pre_cac_adapter:
7666 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307667 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7668 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307669close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307670 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007671release_intf_addr_and_return_failure:
7672 /*
7673 * Release the interface address as the adapter
7674 * failed to start, if you don't release then next
7675 * adapter which is trying to come wouldn't get valid
7676 * mac address. Remember we have limited pool of mac addresses
7677 */
7678 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307679 return -EINVAL;
7680}
7681
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307682static const struct nla_policy
7683wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7684 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7685};
7686
Agrawal Ashish65634612016-08-18 13:24:32 +05307687static const struct nla_policy
7688wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7689 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7690 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7691};
7692
7693/**
7694 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7695 * @wiphy: Pointer to wireless phy
7696 * @wdev: Pointer to wireless device
7697 * @data: Pointer to data
7698 * @data_len: Length of @data
7699 *
7700 * This function parses the incoming NL vendor command data attributes and
7701 * updates the SAP context about channel_hint and DFS mode.
7702 * If channel_hint is set, SAP will choose that channel
7703 * as operating channel.
7704 *
7705 * If DFS mode is enabled, driver will include DFS channels
7706 * in ACS else driver will skip DFS channels.
7707 *
7708 * Return: 0 on success, negative errno on failure
7709 */
7710static int
7711__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7712 struct wireless_dev *wdev,
7713 const void *data, int data_len)
7714{
7715 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7716 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7717 int ret;
7718 struct acs_dfs_policy *acs_policy;
7719 int mode = DFS_MODE_NONE;
7720 int channel_hint = 0;
7721
7722 ENTER_DEV(wdev->netdev);
7723
7724 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7725 hdd_err("Command not allowed in FTM mode");
7726 return -EINVAL;
7727 }
7728
7729 ret = wlan_hdd_validate_context(hdd_ctx);
7730 if (0 != ret)
7731 return ret;
7732
7733 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7734 data, data_len,
7735 wlan_hdd_set_acs_dfs_config_policy)) {
7736 hdd_err("invalid attr");
7737 return -EINVAL;
7738 }
7739
7740 acs_policy = &hdd_ctx->acs_policy;
7741 /*
7742 * SCM sends this attribute to restrict SAP from choosing
7743 * DFS channels from ACS.
7744 */
7745 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7746 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7747
7748 if (!IS_DFS_MODE_VALID(mode)) {
7749 hdd_err("attr acs dfs mode is not valid");
7750 return -EINVAL;
7751 }
7752 acs_policy->acs_dfs_mode = mode;
7753
7754 /*
7755 * SCM sends this attribute to provide an active channel,
7756 * to skip redundant ACS between drivers, and save driver start up time
7757 */
7758 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7759 channel_hint = nla_get_u8(
7760 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7761
7762 if (!IS_CHANNEL_VALID(channel_hint)) {
7763 hdd_err("acs channel is not valid");
7764 return -EINVAL;
7765 }
7766 acs_policy->acs_channel = channel_hint;
7767
7768 return 0;
7769}
7770
7771/**
7772 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7773 * @wiphy: wiphy structure pointer
7774 * @wdev: Wireless device structure pointer
7775 * @data: Pointer to the data received
7776 * @data_len: Length of @data
7777 *
7778 * This function parses the incoming NL vendor command data attributes and
7779 * updates the SAP context about channel_hint and DFS mode.
7780 *
7781 * Return: 0 on success; errno on failure
7782 */
7783static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7784 struct wireless_dev *wdev,
7785 const void *data, int data_len)
7786{
7787 int ret;
7788
7789 cds_ssr_protect(__func__);
7790 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7791 cds_ssr_unprotect(__func__);
7792
7793 return ret;
7794}
7795
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307796/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307797 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7798 * @mode : cfg80211 dfs mode
7799 *
7800 * Return: return csr sta roam dfs mode else return NONE
7801 */
7802static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7803 enum dfs_mode mode)
7804{
7805 switch (mode) {
7806 case DFS_MODE_ENABLE:
7807 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7808 break;
7809 case DFS_MODE_DISABLE:
7810 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7811 break;
7812 case DFS_MODE_DEPRIORITIZE:
7813 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7814 break;
7815 default:
7816 hdd_err("STA Roam policy dfs mode is NONE");
7817 return CSR_STA_ROAM_POLICY_NONE;
7818 }
7819}
7820
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307821/*
7822 * hdd_get_sap_operating_band: Get current operating channel
7823 * for sap.
7824 * @hdd_ctx: hdd context
7825 *
7826 * Return : Corresponding band for SAP operating channel
7827 */
7828uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7829{
7830 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7831 QDF_STATUS status;
7832 hdd_adapter_t *adapter;
7833 uint8_t operating_channel = 0;
7834 uint8_t sap_operating_band = 0;
7835 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7836 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7837 adapter = adapter_node->pAdapter;
7838
7839 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7840 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7841 &next);
7842 adapter_node = next;
7843 continue;
7844 }
7845 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7846 if (IS_24G_CH(operating_channel))
7847 sap_operating_band = eCSR_BAND_24;
7848 else if (IS_5G_CH(operating_channel))
7849 sap_operating_band = eCSR_BAND_5G;
7850 else
7851 sap_operating_band = eCSR_BAND_ALL;
7852 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7853 &next);
bings373b99b2017-01-23 10:35:08 +08007854 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307855 }
7856 return sap_operating_band;
7857}
7858
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307859static const struct nla_policy
7860wlan_hdd_set_sta_roam_config_policy[
7861QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7862 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7863 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7864};
7865
7866/**
7867 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7868 * for station connection or roaming.
7869 * @wiphy: Pointer to wireless phy
7870 * @wdev: Pointer to wireless device
7871 * @data: Pointer to data
7872 * @data_len: Length of @data
7873 *
7874 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7875 * channels needs to be skipped in scanning or not.
7876 * If dfs_mode is disabled, driver will not scan DFS channels.
7877 * If skip_unsafe_channels is set, driver will skip unsafe channels
7878 * in Scanning.
7879 *
7880 * Return: 0 on success, negative errno on failure
7881 */
7882static int
7883__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7884 struct wireless_dev *wdev,
7885 const void *data, int data_len)
7886{
7887 struct net_device *dev = wdev->netdev;
7888 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7889 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7890 struct nlattr *tb[
7891 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7892 int ret;
7893 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7894 enum dfs_mode mode = DFS_MODE_NONE;
7895 bool skip_unsafe_channels = false;
7896 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307897 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307898
7899 ENTER_DEV(dev);
7900
7901 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7902 hdd_err("Command not allowed in FTM mode");
7903 return -EINVAL;
7904 }
7905
7906 ret = wlan_hdd_validate_context(hdd_ctx);
7907 if (0 != ret)
7908 return ret;
7909 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7910 data, data_len,
7911 wlan_hdd_set_sta_roam_config_policy)) {
7912 hdd_err("invalid attr");
7913 return -EINVAL;
7914 }
7915 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7916 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7917 if (!IS_DFS_MODE_VALID(mode)) {
7918 hdd_err("attr sta roam dfs mode policy is not valid");
7919 return -EINVAL;
7920 }
7921
7922 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7923
7924 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7925 skip_unsafe_channels = nla_get_u8(
7926 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307927 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307928 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307929 skip_unsafe_channels, adapter->sessionId,
7930 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307931
7932 if (!QDF_IS_STATUS_SUCCESS(status)) {
7933 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7934 return -EINVAL;
7935 }
7936 return 0;
7937}
7938
7939/**
7940 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7941 * connection and roaming for station.
7942 * @wiphy: wiphy structure pointer
7943 * @wdev: Wireless device structure pointer
7944 * @data: Pointer to the data received
7945 * @data_len: Length of @data
7946 *
7947 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7948 * channels needs to be skipped in scanning or not.
7949 * If dfs_mode is disabled, driver will not scan DFS channels.
7950 * If skip_unsafe_channels is set, driver will skip unsafe channels
7951 * in Scanning.
7952 * Return: 0 on success; errno on failure
7953 */
7954static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7955 struct wireless_dev *wdev,
7956 const void *data, int data_len)
7957{
7958 int ret;
7959
7960 cds_ssr_protect(__func__);
7961 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7962 cds_ssr_unprotect(__func__);
7963
7964 return ret;
7965}
7966
Agrawal Ashish467dde42016-09-08 18:44:22 +05307967#ifdef FEATURE_WLAN_CH_AVOID
7968/**
7969 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7970 * is on unsafe channel.
7971 * @wiphy: wiphy structure pointer
7972 * @wdev: Wireless device structure pointer
7973 * @data: Pointer to the data received
7974 * @data_len: Length of @data
7975 *
7976 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7977 * on any of unsafe channels.
7978 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7979 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7980 *
7981 * Return: 0 on success; errno on failure
7982 */
7983static int
7984__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7985 struct wireless_dev *wdev,
7986 const void *data, int data_len)
7987{
7988 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7989 int ret;
7990 uint16_t unsafe_channel_count;
7991 int unsafe_channel_index;
7992 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7993
7994 ENTER_DEV(wdev->netdev);
7995
7996 if (!qdf_ctx) {
7997 cds_err("qdf_ctx is NULL");
7998 return -EINVAL;
7999 }
8000
8001 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8002 hdd_err("Command not allowed in FTM mode");
8003 return -EINVAL;
8004 }
8005
8006 ret = wlan_hdd_validate_context(hdd_ctx);
8007 if (0 != ret)
8008 return ret;
8009 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8010 &(hdd_ctx->unsafe_channel_count),
8011 sizeof(hdd_ctx->unsafe_channel_list));
8012
8013 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8014 (uint16_t)NUM_CHANNELS);
8015 for (unsafe_channel_index = 0;
8016 unsafe_channel_index < unsafe_channel_count;
8017 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008018 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308019 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8020 }
8021 hdd_unsafe_channel_restart_sap(hdd_ctx);
8022 return 0;
8023}
8024
8025/**
8026 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8027 * is on unsafe channel.
8028 * @wiphy: wiphy structure pointer
8029 * @wdev: Wireless device structure pointer
8030 * @data: Pointer to the data received
8031 * @data_len: Length of @data
8032 *
8033 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8034 * on any of unsafe channels.
8035 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8036 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8037 *
8038 * Return: 0 on success; errno on failure
8039 */
8040static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8041 struct wireless_dev *wdev,
8042 const void *data, int data_len)
8043{
8044 int ret;
8045
8046 cds_ssr_protect(__func__);
8047 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8048 cds_ssr_unprotect(__func__);
8049
8050 return ret;
8051}
8052
8053#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308054/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308055 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8056 * SAP is on unsafe channel.
8057 * @wiphy: wiphy structure pointer
8058 * @wdev: Wireless device structure pointer
8059 * @data: Pointer to the data received
8060 * @data_len: Length of @data
8061 *
8062 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8063 * driver.
8064 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8065 * will initiate restart of sap.
8066 *
8067 * Return: 0 on success; errno on failure
8068 */
8069static int
8070__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8071 struct wireless_dev *wdev,
8072 const void *data, int data_len)
8073{
8074 struct net_device *ndev = wdev->netdev;
8075 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8076 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8077 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8078 uint8_t config_channel = 0;
8079 hdd_ap_ctx_t *ap_ctx;
8080 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308081 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308082
8083 ENTER();
8084
8085 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008086 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308087 return -EINVAL;
8088 }
8089
8090 ret = wlan_hdd_validate_context(hdd_ctx);
8091 if (0 != ret)
8092 return -EINVAL;
8093
8094 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8095 data, data_len,
8096 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008097 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308098 return -EINVAL;
8099 }
8100
8101 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8102 if (!test_bit(SOFTAP_BSS_STARTED,
8103 &hostapd_adapter->event_flags)) {
8104 hdd_err("SAP is not started yet. Restart sap will be invalid");
8105 return -EINVAL;
8106 }
8107
8108 config_channel =
8109 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8110
8111 if (!((IS_24G_CH(config_channel)) ||
8112 (IS_5G_CH(config_channel)))) {
8113 hdd_err("Channel %d is not valid to restart SAP",
8114 config_channel);
8115 return -ENOTSUPP;
8116 }
8117
8118 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8119 ap_ctx->sapConfig.channel = config_channel;
8120 ap_ctx->sapConfig.ch_params.ch_width =
8121 ap_ctx->sapConfig.ch_width_orig;
8122
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008123 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8124 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308125 ap_ctx->sapConfig.sec_ch,
8126 &ap_ctx->sapConfig.ch_params);
8127
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008128 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308129 }
8130
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308131 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8132 uint32_t freq_len, i;
8133 uint32_t *freq;
8134 uint8_t chans[QDF_MAX_NUM_CHAN];
8135
8136 hdd_debug("setting mandatory freq/chan list");
8137
8138 freq_len = nla_len(
8139 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8140 sizeof(uint32_t);
8141
8142 if (freq_len > QDF_MAX_NUM_CHAN) {
8143 hdd_err("insufficient space to hold channels");
8144 return -ENOMEM;
8145 }
8146
8147 freq = nla_data(
8148 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8149
8150 hdd_debug("freq_len=%d", freq_len);
8151
8152 for (i = 0; i < freq_len; i++) {
8153 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8154 hdd_debug("freq[%d]=%d", i, freq[i]);
8155 }
8156
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008157 status = policy_mgr_set_sap_mandatory_channels(
8158 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308159 if (QDF_IS_STATUS_ERROR(status))
8160 return -EINVAL;
8161 }
8162
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308163 return 0;
8164}
8165
8166/**
8167 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8168 * @wiphy: wiphy structure pointer
8169 * @wdev: Wireless device structure pointer
8170 * @data: Pointer to the data received
8171 * @data_len: Length of @data
8172 *
8173 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8174 * driver.
8175 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8176 * will initiate restart of sap.
8177 *
8178 * Return: 0 on success; errno on failure
8179 */
8180static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8181 struct wireless_dev *wdev,
8182 const void *data, int data_len)
8183{
8184 int ret;
8185
8186 cds_ssr_protect(__func__);
8187 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8188 wdev, data, data_len);
8189 cds_ssr_unprotect(__func__);
8190
8191 return ret;
8192}
8193
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308194#undef BPF_INVALID
8195#undef BPF_SET_RESET
8196#undef BPF_VERSION
8197#undef BPF_ID
8198#undef BPF_PACKET_SIZE
8199#undef BPF_CURRENT_OFFSET
8200#undef BPF_PROGRAM
8201#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308202
8203/**
8204 * define short names for the global vendor params
8205 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8206 */
8207#define PARAM_TOTAL_CMD_EVENT_WAKE \
8208 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8209#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8210 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8211#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8212 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8213#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8214 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8215#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8216 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8217#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8218 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8219#define PARAM_TOTAL_RX_DATA_WAKE \
8220 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8221#define PARAM_RX_UNICAST_CNT \
8222 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8223#define PARAM_RX_MULTICAST_CNT \
8224 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8225#define PARAM_RX_BROADCAST_CNT \
8226 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8227#define PARAM_ICMP_PKT \
8228 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8229#define PARAM_ICMP6_PKT \
8230 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8231#define PARAM_ICMP6_RA \
8232 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8233#define PARAM_ICMP6_NA \
8234 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8235#define PARAM_ICMP6_NS \
8236 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8237#define PARAM_ICMP4_RX_MULTICAST_CNT \
8238 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8239#define PARAM_ICMP6_RX_MULTICAST_CNT \
8240 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8241#define PARAM_OTHER_RX_MULTICAST_CNT \
8242 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308243#define PARAM_RSSI_BREACH_CNT \
8244 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8245#define PARAM_LOW_RSSI_CNT \
8246 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8247#define PARAM_GSCAN_CNT \
8248 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8249#define PARAM_PNO_COMPLETE_CNT \
8250 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8251#define PARAM_PNO_MATCH_CNT \
8252 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8253
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308254
8255
8256/**
8257 * hdd_send_wakelock_stats() - API to send wakelock stats
8258 * @ctx: context to be passed to callback
8259 * @data: data passed to callback
8260 *
8261 * This function is used to send wake lock stats to HAL layer
8262 *
8263 * Return: 0 on success, error number otherwise.
8264 */
8265static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8266 const struct sir_wake_lock_stats *data)
8267{
8268 struct sk_buff *skb;
8269 uint32_t nl_buf_len;
8270 uint32_t total_rx_data_wake, rx_multicast_cnt;
8271 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308272 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308273
8274 ENTER();
8275
8276 nl_buf_len = NLMSG_HDRLEN;
8277 nl_buf_len +=
8278 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8279 (NLMSG_HDRLEN + sizeof(uint32_t));
8280
8281 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8282
8283 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008284 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308285 return -ENOMEM;
8286 }
8287
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008288 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308289 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008290 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308291 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008292 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308293 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008294 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308295 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008296 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308297 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008298 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308299 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008300 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308301 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008302 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8303 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308304 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008305 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308306 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008307 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308308 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008309 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308310 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008311 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308312 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008313 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308314 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308315
8316 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308317 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308318
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308319 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308320 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308321
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308322 rx_multicast_cnt =
8323 data->wow_ipv4_mcast_wake_up_count +
8324 ipv6_rx_multicast_addr_cnt;
8325
8326 total_rx_data_wake =
8327 data->wow_ucast_wake_up_count +
8328 data->wow_bcast_wake_up_count +
8329 rx_multicast_cnt;
8330
8331 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8332 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8333 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8334 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8335 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8336 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8337 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8338 total_rx_data_wake) ||
8339 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8340 data->wow_ucast_wake_up_count) ||
8341 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8342 rx_multicast_cnt) ||
8343 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8344 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308345 nla_put_u32(skb, PARAM_ICMP_PKT,
8346 data->wow_icmpv4_count) ||
8347 nla_put_u32(skb, PARAM_ICMP6_PKT,
8348 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308349 nla_put_u32(skb, PARAM_ICMP6_RA,
8350 data->wow_ipv6_mcast_ra_stats) ||
8351 nla_put_u32(skb, PARAM_ICMP6_NA,
8352 data->wow_ipv6_mcast_na_stats) ||
8353 nla_put_u32(skb, PARAM_ICMP6_NS,
8354 data->wow_ipv6_mcast_ns_stats) ||
8355 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8356 data->wow_ipv4_mcast_wake_up_count) ||
8357 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8358 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308359 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8360 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8361 data->wow_rssi_breach_wake_up_count) ||
8362 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8363 data->wow_low_rssi_wake_up_count) ||
8364 nla_put_u32(skb, PARAM_GSCAN_CNT,
8365 data->wow_gscan_wake_up_count) ||
8366 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8367 data->wow_pno_complete_wake_up_count) ||
8368 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8369 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008370 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308371 goto nla_put_failure;
8372 }
8373
8374 cfg80211_vendor_cmd_reply(skb);
8375
8376 EXIT();
8377 return 0;
8378
8379nla_put_failure:
8380 kfree_skb(skb);
8381 return -EINVAL;
8382}
8383
8384/**
8385 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8386 * @wiphy: wiphy pointer
8387 * @wdev: pointer to struct wireless_dev
8388 * @data: pointer to incoming NL vendor data
8389 * @data_len: length of @data
8390 *
8391 * This function parses the incoming NL vendor command data attributes and
8392 * invokes the SME Api and blocks on a completion variable.
8393 * WMA copies required data and invokes callback
8394 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8395 *
8396 * Return: 0 on success; error number otherwise.
8397 */
8398static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8399 struct wireless_dev *wdev,
8400 const void *data,
8401 int data_len)
8402{
8403 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8404 int status, ret;
8405 struct sir_wake_lock_stats wake_lock_stats;
8406 QDF_STATUS qdf_status;
8407
8408 ENTER();
8409
8410 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008411 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308412 return -EINVAL;
8413 }
8414
8415 status = wlan_hdd_validate_context(hdd_ctx);
8416 if (0 != status)
8417 return -EINVAL;
8418
8419 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8420 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008421 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308422 return -EINVAL;
8423 }
8424
8425 ret = hdd_send_wakelock_stats(hdd_ctx,
8426 &wake_lock_stats);
8427 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008428 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308429
8430 EXIT();
8431 return ret;
8432}
8433
8434/**
8435 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8436 * @wiphy: wiphy pointer
8437 * @wdev: pointer to struct wireless_dev
8438 * @data: pointer to incoming NL vendor data
8439 * @data_len: length of @data
8440 *
8441 * This function parses the incoming NL vendor command data attributes and
8442 * invokes the SME Api and blocks on a completion variable.
8443 * WMA copies required data and invokes callback
8444 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8445 *
8446 * Return: 0 on success; error number otherwise.
8447 */
8448static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8449 struct wireless_dev *wdev,
8450 const void *data, int data_len)
8451{
8452 int ret;
8453
8454 cds_ssr_protect(__func__);
8455 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8456 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008457 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308458
8459 return ret;
8460}
8461
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308462/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308463 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8464 * @wiphy: wiphy structure pointer
8465 * @wdev: Wireless device structure pointer
8466 * @data: Pointer to the data received
8467 * @data_len: Length of @data
8468 *
8469 * This function reads wmi max bus size and fill in the skb with
8470 * NL attributes and send up the NL event.
8471 * Return: 0 on success; errno on failure
8472 */
8473static int
8474__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8475 struct wireless_dev *wdev,
8476 const void *data, int data_len)
8477{
8478 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8479 int ret_val;
8480 struct sk_buff *skb;
8481 uint32_t nl_buf_len;
8482
8483 ENTER();
8484
8485 ret_val = wlan_hdd_validate_context(hdd_ctx);
8486 if (ret_val)
8487 return ret_val;
8488
8489 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8490 hdd_err("Command not allowed in FTM mode");
8491 return -EINVAL;
8492 }
8493
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008494 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308495
8496 nl_buf_len = NLMSG_HDRLEN;
8497 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8498
8499 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8500 if (!skb) {
8501 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8502 return -ENOMEM;
8503 }
8504
8505 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8506 hdd_ctx->wmi_max_len)) {
8507 hdd_err("nla put failure");
8508 goto nla_put_failure;
8509 }
8510
8511 cfg80211_vendor_cmd_reply(skb);
8512
8513 EXIT();
8514
8515 return 0;
8516
8517nla_put_failure:
8518 kfree_skb(skb);
8519 return -EINVAL;
8520}
8521
8522/**
8523 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8524 * @wiphy: wiphy structure pointer
8525 * @wdev: Wireless device structure pointer
8526 * @data: Pointer to the data received
8527 * @data_len: Length of @data
8528 *
8529 * Return: 0 on success; errno on failure
8530 */
8531static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8532 struct wireless_dev *wdev,
8533 const void *data, int data_len)
8534{
8535 int ret;
8536
8537 cds_ssr_protect(__func__);
8538 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8539 cds_ssr_unprotect(__func__);
8540
8541 return ret;
8542}
8543
8544/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308545 *__wlan_hdd_cfg80211_setband() - set band
8546 * @wiphy: Pointer to wireless phy
8547 * @wdev: Pointer to wireless device
8548 * @data: Pointer to data
8549 * @data_len: Length of @data
8550 *
8551 * Return: 0 on success, negative errno on failure
8552 */
8553static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8554 struct wireless_dev *wdev,
8555 const void *data, int data_len)
8556{
8557 struct net_device *dev = wdev->netdev;
8558 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8559 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8560 int ret;
8561 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8562 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8563
8564 ENTER();
8565
8566 ret = wlan_hdd_validate_context(hdd_ctx);
8567 if (ret)
8568 return ret;
8569
8570 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8571 hdd_err(FL("Invalid ATTR"));
8572 return -EINVAL;
8573 }
8574
8575 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8576 hdd_err(FL("attr SETBAND_VALUE failed"));
8577 return -EINVAL;
8578 }
8579
8580 ret = hdd_set_band(dev,
8581 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8582
8583 EXIT();
8584 return ret;
8585}
8586
8587/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308588 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8589 * @adapter: hdd adapter
8590 * @channel: channel number
8591 *
8592 * return: QDF status based on success or failure
8593 */
8594static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8595 int channel, int chan_bw)
8596{
8597 if (QDF_STATUS_SUCCESS !=
8598 wlan_hdd_validate_operation_channel(adapter, channel))
8599 return QDF_STATUS_E_FAILURE;
8600 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8601 channel,
8602 PHY_SINGLE_CHANNEL_CENTERED))) {
8603 hdd_notice("channel %d is in nol", channel);
8604 return -EINVAL;
8605 }
8606
8607 if ((wlansap_is_channel_leaking_in_nol(
8608 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8609 channel, chan_bw))) {
8610 hdd_notice("channel %d is leaking in nol", channel);
8611 return -EINVAL;
8612 }
8613
8614 return 0;
8615
8616}
8617
Kapil Gupta8878ad92017-02-13 11:56:04 +05308618static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8619 tsap_Config_t *sap_config,
8620 struct hdd_vendor_chan_info *channel_list)
8621{
8622 sap_config->channel = channel_list->pri_ch;
8623
8624 sap_config->ch_params.center_freq_seg0 =
8625 channel_list->vht_seg0_center_ch;
8626 sap_config->ch_params.center_freq_seg1 =
8627 channel_list->vht_seg1_center_ch;
8628
8629 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8630 sap_config->ch_params.ch_width = channel_list->chan_width;
8631 if (sap_config->channel >= 36)
8632 sap_config->ch_width_orig =
8633 hdd_ctx->config->vhtChannelWidth;
8634 else
8635 sap_config->ch_width_orig =
8636 hdd_ctx->config->nChannelBondingMode24GHz ?
8637 eHT_CHANNEL_WIDTH_40MHZ :
8638 eHT_CHANNEL_WIDTH_20MHZ;
8639
8640 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8641 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8642 sap_config->acs_cfg.vht_seg0_center_ch =
8643 channel_list->vht_seg0_center_ch;
8644 sap_config->acs_cfg.vht_seg1_center_ch =
8645 channel_list->vht_seg1_center_ch;
8646 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8647}
8648
8649static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8650 uint8_t channel_cnt,
8651 struct hdd_vendor_chan_info *channel_list)
8652{
8653 tsap_Config_t *sap_config;
8654 hdd_ap_ctx_t *hdd_ap_ctx;
8655 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8656 QDF_STATUS status = QDF_STATUS_SUCCESS;
8657
8658 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8659 sap_config = &adapter->sessionCtx.ap.sapConfig;
8660
8661 if (QDF_TIMER_STATE_RUNNING ==
8662 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8663 ap.vendor_acs_timer)) {
8664 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8665 }
8666
8667 if (channel_list && channel_list->pri_ch == 0) {
8668 /* Check mode, set default channel */
8669 channel_list->pri_ch = 6;
8670 /*
8671 * sap_select_default_oper_chan(hdd_ctx->hHal,
8672 * sap_config->acs_cfg.hw_mode);
8673 */
8674 }
8675
8676 switch (reason) {
8677 /* SAP init case */
8678 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8679 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8680 /* Update Hostapd */
8681 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8682 break;
8683
8684 /* DFS detected on current channel */
8685 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8686 wlan_sap_update_next_channel(
8687 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8688 channel_list->pri_ch,
8689 channel_list->chan_width);
8690 status = sme_update_new_channel_event(
8691 WLAN_HDD_GET_HAL_CTX(adapter),
8692 adapter->sessionId);
8693 break;
8694
8695 /* LTE coex event on current channel */
8696 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8697 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8698 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8699 hdd_ap_ctx->sapConfig.ch_width_orig =
8700 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008701 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308702 break;
8703
8704 default:
8705 hdd_info("invalid reason for timer invoke");
8706 }
8707 qdf_mem_free(channel_list);
8708 EXIT();
8709 return status;
8710}
8711
8712/**
8713 * Define short name for vendor channel set config
8714 */
8715#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8716#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8717#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8718#define SET_CHAN_PRIMARY_CHANNEL \
8719 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8720#define SET_CHAN_SECONDARY_CHANNEL \
8721 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8722#define SET_CHAN_SEG0_CENTER_CHANNEL \
8723 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8724#define SET_CHAN_SEG1_CENTER_CHANNEL \
8725 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8726#define SET_CHAN_CHANNEL_WIDTH \
8727 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8728#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8729
8730/**
8731 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8732 * @channel_list: pointer to hdd_vendor_chan_info
8733 * @reason: channel change reason
8734 * @channel_cnt: channel count
8735 * @data: data
8736 * @data_len: data len
8737 *
8738 * Return: 0 on success, negative errno on failure
8739 */
8740static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8741 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8742 const void *data, int data_len)
8743{
8744 int rem, i = 0;
8745 struct nlattr *tb[SET_CHAN_MAX + 1];
8746 struct nlattr *tb2[SET_CHAN_MAX + 1];
8747 struct nlattr *curr_attr;
8748 struct hdd_vendor_chan_info *channel_list;
8749
8750 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8751 hdd_err("Invalid ATTR");
8752 return -EINVAL;
8753 }
8754
8755 if (tb[SET_CHAN_REASON])
8756 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8757
8758 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8759 *channel_cnt = nla_get_u8(tb[
8760 SET_CHAN_CHANNEL_COUNT]);
8761 hdd_info("channel count %d", *channel_cnt);
8762 }
8763
8764 if (!(*channel_cnt)) {
8765 hdd_err("channel count is %d", *channel_cnt);
8766 return -EINVAL;
8767 }
8768
8769 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8770 (*channel_cnt));
8771
8772 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8773 if (nla_parse(tb2,
8774 SET_CHAN_MAX,
8775 nla_data(curr_attr), nla_len(curr_attr),
8776 NULL)) {
8777 hdd_err("nla_parse failed");
8778 return -EINVAL;
8779 }
8780 /* Parse and Fetch allowed SSID list*/
8781 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8782 channel_list[i].pri_ch =
8783 nla_get_u8(
8784 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8785 }
8786 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8787 channel_list[i].ht_sec_ch =
8788 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8789 }
8790 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8791 channel_list[i].vht_seg0_center_ch =
8792 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8793 }
8794 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8795 channel_list[i].vht_seg1_center_ch =
8796 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8797 }
8798 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8799 channel_list[i].chan_width =
8800 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8801 }
8802 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8803 i, channel_list[i].pri_ch,
8804 channel_list[i].ht_sec_ch,
8805 channel_list[i].vht_seg0_center_ch,
8806 channel_list[i].vht_seg1_center_ch,
8807 channel_list[i].chan_width);
8808 i++;
8809 if (i > *channel_cnt)
8810 break;
8811 }
8812 *chan_list_ptr = channel_list;
8813
8814 return 0;
8815}
8816
8817/**
8818 * Undef short names for vendor set channel configuration
8819 */
8820#undef SET_CHAN_REASON
8821#undef SET_CHAN_CHANNEL_COUNT
8822#undef SET_CHAN_CHAN_LIST
8823#undef SET_CHAN_PRIMARY_CHANNEL
8824#undef SET_CHAN_SECONDARY_CHANNEL
8825#undef SET_CHAN_SEG0_CENTER_CHANNEL
8826#undef SET_CHAN_SEG1_CENTER_CHANNEL
8827#undef SET_CHAN_CHANNEL_WIDTH
8828#undef SET_CHAN_MAX
8829
8830/**
8831 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8832 * @wiphy: Pointer to wireless phy
8833 * @wdev: Pointer to wireless device
8834 * @data: Pointer to data
8835 * @data_len: Length of @data
8836 *
8837 * Return: 0 on success, negative errno on failure
8838 */
8839static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8840 struct wireless_dev *wdev,
8841 const void *data, int data_len)
8842{
8843 int ret_val;
8844 QDF_STATUS qdf_status;
8845 uint8_t channel_cnt = 0, reason = -1;
8846 struct hdd_vendor_chan_info *channel_list = NULL;
8847 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8848 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8849
8850 ENTER();
8851
8852 ret_val = wlan_hdd_validate_context(hdd_ctx);
8853 if (ret_val)
8854 return ret_val;
8855
8856 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8857 hdd_err("Command not allowed in FTM mode");
8858 return -EINVAL;
8859 }
8860
8861 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8862 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8863 else {
8864 hdd_err("already timeout happened for acs");
8865 return -EINVAL;
8866 }
8867
8868 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8869 &channel_cnt, data, data_len);
8870 if (ret_val)
8871 return ret_val;
8872
8873 /* Validate channel to be set */
8874 while (channel_cnt && channel_list) {
8875 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8876 channel_list->pri_ch,
8877 channel_list->chan_width);
8878 if (qdf_status == QDF_STATUS_SUCCESS)
8879 break;
8880 channel_cnt--;
8881 channel_list++;
8882 }
8883 if ((channel_cnt <= 0) || !channel_list) {
8884 hdd_err("no available channel/chanlist %p", channel_list);
8885 return -EINVAL;
8886 }
8887
8888 qdf_status = hdd_update_acs_channel(adapter, reason,
8889 channel_cnt, channel_list);
8890 return qdf_status_to_os_return(qdf_status);
8891}
8892
8893/**
8894 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8895 * @wiphy: Pointer to wireless phy
8896 * @wdev: Pointer to wireless device
8897 * @data: Pointer to data
8898 * @data_len: Length of @data
8899 *
8900 * Return: 0 on success, negative errno on failure
8901 */
8902static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8903 struct wireless_dev *wdev,
8904 const void *data, int data_len)
8905{
8906 int ret;
8907
8908 cds_ssr_protect(__func__);
8909 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8910 data_len);
8911 cds_ssr_protect(__func__);
8912
8913 return ret;
8914}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308915
8916/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308917 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8918 * @wiphy: wiphy structure pointer
8919 * @wdev: Wireless device structure pointer
8920 * @data: Pointer to the data received
8921 * @data_len: Length of @data
8922 *
8923 * Return: 0 on success; errno on failure
8924 */
8925static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8926 struct wireless_dev *wdev,
8927 const void *data, int data_len)
8928{
8929 int ret;
8930
8931 cds_ssr_protect(__func__);
8932 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8933 cds_ssr_unprotect(__func__);
8934
8935 return ret;
8936}
8937
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008938/**
8939 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8940 * @nl80211_value: Vendor command attribute value
8941 * @wmi_value: Pointer to return converted WMI return value
8942 *
8943 * Convert NL80211 vendor command value for SAR limit set to WMI value
8944 * Return: 0 on success, -1 on invalid value
8945 */
8946static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8947 u32 *wmi_value)
8948{
8949 int ret = 0;
8950
8951 switch (nl80211_value) {
8952 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8953 *wmi_value = WMI_SAR_FEATURE_OFF;
8954 break;
8955 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8956 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8957 break;
8958 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8959 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8960 break;
8961 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8962 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8963 break;
8964 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8965 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8966 break;
8967 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8968 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8969 break;
8970 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8971 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8972 break;
8973 default:
8974 ret = -1;
8975 }
8976 return ret;
8977}
8978
8979/**
8980 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band 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 BAND to WMI value
8985 * Return: 0 on success, -1 on invalid value
8986 */
8987static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8988{
8989 int ret = 0;
8990
8991 switch (nl80211_value) {
8992 case NL80211_BAND_2GHZ:
8993 *wmi_value = WMI_SAR_2G_ID;
8994 break;
8995 case NL80211_BAND_5GHZ:
8996 *wmi_value = WMI_SAR_5G_ID;
8997 break;
8998 default:
8999 ret = -1;
9000 }
9001 return ret;
9002}
9003
9004/**
9005 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9006 * @nl80211_value: Vendor command attribute value
9007 * @wmi_value: Pointer to return converted WMI return value
9008 *
9009 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9010 * Return: 0 on success, -1 on invalid value
9011 */
9012static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9013 u32 *wmi_value)
9014{
9015 int ret = 0;
9016
9017 switch (nl80211_value) {
9018 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9019 *wmi_value = WMI_SAR_MOD_CCK;
9020 break;
9021 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9022 *wmi_value = WMI_SAR_MOD_OFDM;
9023 break;
9024 default:
9025 ret = -1;
9026 }
9027 return ret;
9028}
9029
9030
9031/**
9032 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9033 * @wiphy: Pointer to wireless phy
9034 * @wdev: Pointer to wireless device
9035 * @data: Pointer to data
9036 * @data_len: Length of @data
9037 *
9038 * This function is used to setup Specific Absorption Rate limit specs.
9039 *
9040 * Return: 0 on success, negative errno on failure
9041 */
9042static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9043 struct wireless_dev *wdev,
9044 const void *data, int data_len)
9045{
9046 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9047 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9048 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9049 *sar_spec_list;
9050 struct sar_limit_cmd_params sar_limit_cmd = {0};
9051 int ret = -EINVAL, i = 0, rem = 0;
9052
9053 ENTER();
9054
9055 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9056 hdd_err("Command not allowed in FTM mode");
9057 return -EPERM;
9058 }
9059
9060 if (wlan_hdd_validate_context(hdd_ctx))
9061 return -EINVAL;
9062
9063 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9064 data, data_len, NULL)) {
9065 hdd_err("Invalid SAR attributes");
9066 return -EINVAL;
9067 }
9068
9069 /* Vendor command manadates all SAR Specs in single call */
9070 sar_limit_cmd.commit_limits = 1;
9071 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9072 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9073 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9074 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9075 &sar_limit_cmd.sar_enable) < 0) {
9076 hdd_err("Invalid SAR Enable attr");
9077 goto fail;
9078 }
9079 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009080 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009081
9082 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9083 sar_limit_cmd.num_limit_rows = nla_get_u32(
9084 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009085 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009086 sar_limit_cmd.num_limit_rows);
9087 }
9088 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9089 hdd_err("SAR Spec list exceed supported size");
9090 goto fail;
9091 }
9092 if (sar_limit_cmd.num_limit_rows == 0)
9093 goto send_sar_limits;
9094 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9095 struct sar_limit_cmd_row) *
9096 sar_limit_cmd.num_limit_rows);
9097 if (!sar_limit_cmd.sar_limit_row_list) {
9098 ret = -ENOMEM;
9099 goto fail;
9100 }
9101 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9102 hdd_err("Invalid SAR SPECs list");
9103 goto fail;
9104 }
9105
9106 nla_for_each_nested(sar_spec_list,
9107 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9108 if (i == sar_limit_cmd.num_limit_rows) {
9109 hdd_warn("SAR Cmd has excess SPECs in list");
9110 break;
9111 }
9112
9113 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9114 nla_data(sar_spec_list), nla_len(sar_spec_list),
9115 NULL)) {
9116 hdd_err("nla_parse failed for SAR Spec list");
9117 goto fail;
9118 }
9119 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9120 if (sar_spec[
9121 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9122 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9123 nla_get_u32(sar_spec[
9124 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9125 } else {
9126 hdd_err("SAR Spec does not have power limit value");
9127 goto fail;
9128 }
9129
9130 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9131 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9132 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9133 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9134 < 0) {
9135 hdd_err("Invalid SAR Band attr");
9136 goto fail;
9137 }
9138 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9139 WMI_SAR_BAND_ID_VALID_MASK;
9140 }
9141 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9142 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9143 nla_get_u32(sar_spec[
9144 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9145 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9146 WMI_SAR_CHAIN_ID_VALID_MASK;
9147 }
9148 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9149 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9150 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9151 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9152 < 0) {
9153 hdd_err("Invalid SAR Modulation attr");
9154 goto fail;
9155 }
9156 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9157 WMI_SAR_MOD_ID_VALID_MASK;
9158 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009159 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009160 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9161 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9162 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9163 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9164 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9165 i++;
9166 }
9167
9168 if (i < sar_limit_cmd.num_limit_rows) {
9169 hdd_warn("SAR Cmd has less SPECs in list");
9170 sar_limit_cmd.num_limit_rows = i;
9171 }
9172
9173send_sar_limits:
9174 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9175 QDF_STATUS_SUCCESS)
9176 ret = 0;
9177fail:
9178 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9179 return ret;
9180}
9181
9182/**
9183 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9184 * @wiphy: Pointer to wireless phy
9185 * @wdev: Pointer to wireless device
9186 * @data: Pointer to data
9187 * @data_len: Length of @data
9188 *
9189 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9190 *
9191 * Return: 0 on success, negative errno on failure
9192 */
9193static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9194 struct wireless_dev *wdev,
9195 const void *data,
9196 int data_len)
9197{
9198 int ret;
9199
9200 cds_ssr_protect(__func__);
9201 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9202 data_len);
9203 cds_ssr_unprotect(__func__);
9204
9205 return ret;
9206}
9207
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309208static const struct
9209nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9210 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9211 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9212 .len = QDF_MAC_ADDR_SIZE},
9213};
9214
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309215void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9216{
9217 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9218 hdd_adapter_t *adapter;
9219
9220 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9221 if (!adapter) {
9222 hdd_err("adapter NULL");
9223 return;
9224 }
9225
9226 adapter->lfr_fw_status.is_disabled = rso_status->status;
9227 complete(&adapter->lfr_fw_status.disable_lfr_event);
9228}
9229
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309230/**
9231 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9232 * @wiphy: Pointer to wireless phy
9233 * @wdev: Pointer to wireless device
9234 * @data: Pointer to data
9235 * @data_len: Length of @data
9236 *
9237 * This function is used to enable/disable roaming using vendor commands
9238 *
9239 * Return: 0 on success, negative errno on failure
9240 */
9241static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9242 struct wireless_dev *wdev,
9243 const void *data, int data_len)
9244{
9245 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9246 struct net_device *dev = wdev->netdev;
9247 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9248 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309249 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309250 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309251 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309252 unsigned long rc;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309253
9254 ENTER_DEV(dev);
9255
9256 ret = wlan_hdd_validate_context(hdd_ctx);
9257 if (0 != ret)
9258 return ret;
9259
9260 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9261 hdd_err("Command not allowed in FTM mode");
9262 return -EINVAL;
9263 }
9264
9265 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9266 qca_wlan_vendor_attr);
9267 if (ret) {
9268 hdd_err("Invalid ATTR");
9269 return -EINVAL;
9270 }
9271
9272 /* Parse and fetch Enable flag */
9273 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9274 hdd_err("attr enable failed");
9275 return -EINVAL;
9276 }
9277
9278 is_fast_roam_enabled = nla_get_u32(
9279 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009280 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009281 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309282
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009283 if (!adapter->fast_roaming_allowed) {
9284 hdd_err("fast roaming not allowed on %s interface",
9285 adapter->dev->name);
9286 return -EINVAL;
9287 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309288 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309289 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309290 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309291 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309292 if (qdf_status != QDF_STATUS_SUCCESS)
9293 hdd_err("sme_config_fast_roaming failed with status=%d",
9294 qdf_status);
9295 ret = qdf_status_to_os_return(qdf_status);
9296
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309297 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
9298 if (QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9299 /*
9300 * wait only for LFR disable in fw as LFR enable
9301 * is always success
9302 */
9303 rc = wait_for_completion_timeout(
9304 &adapter->lfr_fw_status.disable_lfr_event,
9305 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9306 if (!rc) {
9307 hdd_err("Timed out waiting for RSO CMD status");
9308 return -ETIMEDOUT;
9309 }
9310
9311 if (!adapter->lfr_fw_status.is_disabled) {
9312 hdd_err("Roam disable attempt in FW fails");
9313 return -EBUSY;
9314 }
9315 }
9316
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309317 EXIT();
9318 return ret;
9319}
9320
9321/**
9322 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9323 * @wiphy: Pointer to wireless phy
9324 * @wdev: Pointer to wireless device
9325 * @data: Pointer to data
9326 * @data_len: Length of @data
9327 *
9328 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9329 *
9330 * Return: 0 on success, negative errno on failure
9331 */
9332static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9333 struct wireless_dev *wdev,
9334 const void *data, int data_len)
9335{
9336 int ret;
9337
9338 cds_ssr_protect(__func__);
9339 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9340 cds_ssr_unprotect(__func__);
9341
9342 return ret;
9343}
9344
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309345
9346void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9347 uint32_t vdev_id)
9348{
9349 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9350 int status;
9351 hdd_adapter_t *adapter = NULL;
9352 hdd_station_ctx_t *hdd_sta_ctx;
9353
9354 status = wlan_hdd_validate_context(hdd_ctx);
9355 if (status != 0)
9356 return;
9357
9358 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9359 if (adapter == NULL) {
9360 hdd_err("vdev_id %d does not exist with host", vdev_id);
9361 return;
9362 }
9363
9364 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9365 hdd_sta_ctx->conn_info.cca = congestion;
9366 hdd_info("congestion:%d", congestion);
9367}
9368
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309369static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9370 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9371 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9372 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9373 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9374};
9375
9376/**
9377 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9378 * @wiphy: Pointer to wireless phy
9379 * @wdev: Pointer to wireless device
9380 * @data: Pointer to data
9381 * @data_len: Length of @data
9382 *
9383 * Return: 0 on success, negative errno on failure
9384 */
9385static int
9386__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9387 struct wireless_dev *wdev,
9388 const void *data,
9389 int data_len)
9390{
9391 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9392 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9393 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9394 struct nlattr *apth;
9395 int rem;
9396 int ret = 1;
9397 int print_idx = -1;
9398 int module_id = -1;
9399 int bit_mask = -1;
9400 int status;
9401
9402 ENTER();
9403
9404 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9405 hdd_err("Command not allowed in FTM mode");
9406 return -EINVAL;
9407 }
9408
9409 ret = wlan_hdd_validate_context(hdd_ctx);
9410 if (ret != 0)
9411 return -EINVAL;
9412
9413 print_idx = qdf_get_pidx();
9414 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9415 hdd_err("Invalid print controle object index");
9416 return -EINVAL;
9417 }
9418
9419 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9420 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9421 hdd_err("Invalid attr");
9422 return -EINVAL;
9423 }
9424
9425 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9426 hdd_err("attr trace level param failed");
9427 return -EINVAL;
9428 }
9429
9430 nla_for_each_nested(apth,
9431 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9432 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9433 nla_data(apth), nla_len(apth), NULL)) {
9434 hdd_err("Invalid attr");
9435 return -EINVAL;
9436 }
9437
9438 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9439 hdd_err("attr Module ID failed");
9440 return -EINVAL;
9441 }
9442 module_id = nla_get_u32
9443 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9444
9445 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9446 hdd_err("attr Verbose mask failed");
9447 return -EINVAL;
9448 }
9449 bit_mask = nla_get_u32
9450 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9451
9452 status = hdd_qdf_trace_enable(module_id, bit_mask);
9453
9454 if (status != 0)
9455 hdd_err("can not set verbose mask %d for the category %d",
9456 bit_mask, module_id);
9457 }
9458
9459 EXIT();
9460 return ret;
9461}
9462
9463/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309464 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9465 * @wiphy: Pointer to wireless phy
9466 * @wdev: Pointer to wireless device
9467 * @data: Pointer to data
9468 * @data_len: Length of @data
9469 *
9470 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9471 *
9472 * Return: 0 on success, negative errno on failure
9473 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309474
9475static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9476 struct wireless_dev *wdev,
9477 const void *data,
9478 int data_len)
9479{
9480 int ret;
9481
9482 cds_ssr_protect(__func__);
9483 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9484 cds_ssr_unprotect(__func__);
9485
9486 return ret;
9487}
9488
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009489const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9490 {
9491 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9492 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9493 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309494 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009495 .doit = is_driver_dfs_capable
9496 },
9497
9498#ifdef WLAN_FEATURE_NAN
9499 {
9500 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9501 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9502 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9503 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9504 .doit = wlan_hdd_cfg80211_nan_request
9505 },
9506#endif
9507
9508#ifdef WLAN_FEATURE_STATS_EXT
9509 {
9510 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9511 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9512 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9513 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9514 .doit = wlan_hdd_cfg80211_stats_ext_request
9515 },
9516#endif
9517#ifdef FEATURE_WLAN_EXTSCAN
9518 {
9519 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9520 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9521 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9522 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9523 .doit = wlan_hdd_cfg80211_extscan_start
9524 },
9525 {
9526 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9527 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9528 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9529 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9530 .doit = wlan_hdd_cfg80211_extscan_stop
9531 },
9532 {
9533 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9534 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9535 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9536 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9537 },
9538 {
9539 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9540 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9541 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9542 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9543 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9544 },
9545 {
9546 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9547 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9548 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9549 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9550 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9551 },
9552 {
9553 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9554 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9555 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9556 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9557 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9558 },
9559 {
9560 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9561 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9562 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9563 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9564 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9565 },
9566 {
9567 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9568 .info.subcmd =
9569 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9570 .flags =
9571 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9572 WIPHY_VENDOR_CMD_NEED_RUNNING,
9573 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9574 },
9575 {
9576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9577 .info.subcmd =
9578 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9579 .flags =
9580 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9581 WIPHY_VENDOR_CMD_NEED_RUNNING,
9582 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9583 },
9584 {
9585 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9586 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9587 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9588 WIPHY_VENDOR_CMD_NEED_NETDEV |
9589 WIPHY_VENDOR_CMD_NEED_RUNNING,
9590 .doit = wlan_hdd_cfg80211_set_epno_list
9591 },
9592#endif /* FEATURE_WLAN_EXTSCAN */
9593
9594#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9595 {
9596 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9597 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9598 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9599 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9600 .doit = wlan_hdd_cfg80211_ll_stats_clear
9601 },
9602
9603 {
9604 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9605 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9606 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9607 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9608 .doit = wlan_hdd_cfg80211_ll_stats_set
9609 },
9610
9611 {
9612 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9613 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9614 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9615 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9616 .doit = wlan_hdd_cfg80211_ll_stats_get
9617 },
9618#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9619#ifdef FEATURE_WLAN_TDLS
9620 {
9621 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9622 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9623 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9624 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9625 .doit = wlan_hdd_cfg80211_exttdls_enable
9626 },
9627 {
9628 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9629 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9630 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9631 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9632 .doit = wlan_hdd_cfg80211_exttdls_disable
9633 },
9634 {
9635 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9636 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9637 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9638 .doit = wlan_hdd_cfg80211_exttdls_get_status
9639 },
9640#endif
9641 {
9642 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9643 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9644 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9645 .doit = wlan_hdd_cfg80211_get_supported_features
9646 },
9647 {
9648 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9649 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9650 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9651 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9652 },
9653 {
9654 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9655 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9656 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309657 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009658 },
9659 {
9660 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9661 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9662 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9663 WIPHY_VENDOR_CMD_NEED_NETDEV,
9664 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9665 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009666 {
9667 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9668 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9669 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9670 WIPHY_VENDOR_CMD_NEED_NETDEV,
9671 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9672 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009673 {
9674 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309675 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9676 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9677 WIPHY_VENDOR_CMD_NEED_NETDEV |
9678 WIPHY_VENDOR_CMD_NEED_RUNNING,
9679 .doit = hdd_cfg80211_get_station_cmd
9680 },
9681 {
9682 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009683 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9684 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9685 WIPHY_VENDOR_CMD_NEED_NETDEV |
9686 WIPHY_VENDOR_CMD_NEED_RUNNING,
9687 .doit = wlan_hdd_cfg80211_do_acs
9688 },
9689
9690 {
9691 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9692 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9693 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9694 WIPHY_VENDOR_CMD_NEED_NETDEV,
9695 .doit = wlan_hdd_cfg80211_get_features
9696 },
9697#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9698 {
9699 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9700 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9701 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9702 WIPHY_VENDOR_CMD_NEED_NETDEV |
9703 WIPHY_VENDOR_CMD_NEED_RUNNING,
9704 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9705 },
9706#endif
9707#ifdef FEATURE_WLAN_EXTSCAN
9708 {
9709 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9710 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9711 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9712 WIPHY_VENDOR_CMD_NEED_NETDEV |
9713 WIPHY_VENDOR_CMD_NEED_RUNNING,
9714 .doit = wlan_hdd_cfg80211_set_passpoint_list
9715 },
9716 {
9717 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9718 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9719 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9720 WIPHY_VENDOR_CMD_NEED_NETDEV |
9721 WIPHY_VENDOR_CMD_NEED_RUNNING,
9722 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9723 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009724#endif /* FEATURE_WLAN_EXTSCAN */
9725 {
9726 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9727 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9728 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9729 WIPHY_VENDOR_CMD_NEED_NETDEV,
9730 .doit = wlan_hdd_cfg80211_get_wifi_info
9731 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009732#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009733 {
9734 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9735 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9736 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9737 WIPHY_VENDOR_CMD_NEED_NETDEV |
9738 WIPHY_VENDOR_CMD_NEED_RUNNING,
9739 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9740 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009741#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009742 {
9743 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9744 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9745 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9746 WIPHY_VENDOR_CMD_NEED_NETDEV,
9747 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9748 },
9749 {
9750 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9751 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9752 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9753 WIPHY_VENDOR_CMD_NEED_NETDEV,
9754 .doit = wlan_hdd_cfg80211_wifi_logger_start
9755 },
9756 {
9757 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9758 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9759 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9760 WIPHY_VENDOR_CMD_NEED_NETDEV,
9761 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9762 },
9763 {
9764 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9765 .info.subcmd =
9766 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9767 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9768 WIPHY_VENDOR_CMD_NEED_NETDEV |
9769 WIPHY_VENDOR_CMD_NEED_RUNNING,
9770 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9771 },
9772 {
9773 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9774 .info.subcmd =
9775 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9776 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9777 WIPHY_VENDOR_CMD_NEED_NETDEV |
9778 WIPHY_VENDOR_CMD_NEED_RUNNING,
9779 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9780 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009781#ifdef WLAN_FEATURE_TSF
9782 {
9783 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9784 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9785 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9786 WIPHY_VENDOR_CMD_NEED_NETDEV |
9787 WIPHY_VENDOR_CMD_NEED_RUNNING,
9788 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9789 },
9790#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009791#ifdef FEATURE_WLAN_TDLS
9792 {
9793 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9794 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9795 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9796 WIPHY_VENDOR_CMD_NEED_NETDEV |
9797 WIPHY_VENDOR_CMD_NEED_RUNNING,
9798 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9799 },
9800#endif
9801#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9802 {
9803 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9804 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9805 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9806 WIPHY_VENDOR_CMD_NEED_NETDEV |
9807 WIPHY_VENDOR_CMD_NEED_RUNNING,
9808 .doit = wlan_hdd_cfg80211_offloaded_packets
9809 },
9810#endif
9811 {
9812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9813 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9814 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9815 WIPHY_VENDOR_CMD_NEED_NETDEV |
9816 WIPHY_VENDOR_CMD_NEED_RUNNING,
9817 .doit = wlan_hdd_cfg80211_monitor_rssi
9818 },
9819 {
9820 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309821 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9822 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9823 WIPHY_VENDOR_CMD_NEED_NETDEV |
9824 WIPHY_VENDOR_CMD_NEED_RUNNING,
9825 .doit = wlan_hdd_cfg80211_set_ns_offload
9826 },
9827 {
9828 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009829 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9830 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9831 WIPHY_VENDOR_CMD_NEED_NETDEV |
9832 WIPHY_VENDOR_CMD_NEED_RUNNING,
9833 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9834 },
9835#ifdef WLAN_FEATURE_MEMDUMP
9836 {
9837 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9838 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9839 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9840 WIPHY_VENDOR_CMD_NEED_NETDEV |
9841 WIPHY_VENDOR_CMD_NEED_RUNNING,
9842 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9843 },
9844#endif /* WLAN_FEATURE_MEMDUMP */
9845 {
9846 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9847 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9848 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9849 WIPHY_VENDOR_CMD_NEED_NETDEV |
9850 WIPHY_VENDOR_CMD_NEED_RUNNING,
9851 .doit = wlan_hdd_cfg80211_vendor_scan
9852 },
9853
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309854 /* Vendor abort scan */
9855 {
9856 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9857 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9858 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9859 WIPHY_VENDOR_CMD_NEED_NETDEV |
9860 WIPHY_VENDOR_CMD_NEED_RUNNING,
9861 .doit = wlan_hdd_vendor_abort_scan
9862 },
9863
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009864 /* OCB commands */
9865 {
9866 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9867 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9868 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9869 WIPHY_VENDOR_CMD_NEED_NETDEV |
9870 WIPHY_VENDOR_CMD_NEED_RUNNING,
9871 .doit = wlan_hdd_cfg80211_ocb_set_config
9872 },
9873 {
9874 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9875 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9876 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9877 WIPHY_VENDOR_CMD_NEED_NETDEV |
9878 WIPHY_VENDOR_CMD_NEED_RUNNING,
9879 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9880 },
9881 {
9882 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9883 .info.subcmd =
9884 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9885 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9886 WIPHY_VENDOR_CMD_NEED_NETDEV |
9887 WIPHY_VENDOR_CMD_NEED_RUNNING,
9888 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9889 },
9890 {
9891 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9892 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9893 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9894 WIPHY_VENDOR_CMD_NEED_NETDEV |
9895 WIPHY_VENDOR_CMD_NEED_RUNNING,
9896 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9897 },
9898 {
9899 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9900 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9901 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9902 WIPHY_VENDOR_CMD_NEED_NETDEV |
9903 WIPHY_VENDOR_CMD_NEED_RUNNING,
9904 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9905 },
9906 {
9907 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9908 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9909 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9910 WIPHY_VENDOR_CMD_NEED_NETDEV |
9911 WIPHY_VENDOR_CMD_NEED_RUNNING,
9912 .doit = wlan_hdd_cfg80211_dcc_get_stats
9913 },
9914 {
9915 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9916 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9917 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9918 WIPHY_VENDOR_CMD_NEED_NETDEV |
9919 WIPHY_VENDOR_CMD_NEED_RUNNING,
9920 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9921 },
9922 {
9923 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9924 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9925 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9926 WIPHY_VENDOR_CMD_NEED_NETDEV |
9927 WIPHY_VENDOR_CMD_NEED_RUNNING,
9928 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9929 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309930 {
9931 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9932 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9933 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9934 WIPHY_VENDOR_CMD_NEED_NETDEV |
9935 WIPHY_VENDOR_CMD_NEED_RUNNING,
9936 .doit = wlan_hdd_cfg80211_get_link_properties
9937 },
Peng Xu278d0122015-09-24 16:34:17 -07009938 {
Peng Xud2220962016-07-11 17:59:17 -07009939 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009940 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9941 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9942 WIPHY_VENDOR_CMD_NEED_NETDEV |
9943 WIPHY_VENDOR_CMD_NEED_RUNNING,
9944 .doit = wlan_hdd_cfg80211_set_ota_test
9945 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009946#ifdef FEATURE_LFR_SUBNET_DETECTION
9947 {
9948 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9949 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9950 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9951 WIPHY_VENDOR_CMD_NEED_NETDEV |
9952 WIPHY_VENDOR_CMD_NEED_RUNNING,
9953 .doit = wlan_hdd_cfg80211_set_gateway_params
9954 },
9955#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009956 {
Peng Xud2220962016-07-11 17:59:17 -07009957 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009958 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9959 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9960 WIPHY_VENDOR_CMD_NEED_NETDEV |
9961 WIPHY_VENDOR_CMD_NEED_RUNNING,
9962 .doit = wlan_hdd_cfg80211_txpower_scale
9963 },
9964 {
9965 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9966 .info.subcmd =
9967 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9968 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9969 WIPHY_VENDOR_CMD_NEED_NETDEV |
9970 WIPHY_VENDOR_CMD_NEED_RUNNING,
9971 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9972 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309973 {
9974 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9975 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9976 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9977 WIPHY_VENDOR_CMD_NEED_NETDEV |
9978 WIPHY_VENDOR_CMD_NEED_RUNNING,
9979 .doit = wlan_hdd_cfg80211_bpf_offload
9980 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309981 {
9982 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309983 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9984 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9985 WIPHY_VENDOR_CMD_NEED_NETDEV |
9986 WIPHY_VENDOR_CMD_NEED_RUNNING,
9987 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9988 },
9989 {
9990 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309991 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9992 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9993 WIPHY_VENDOR_CMD_NEED_NETDEV |
9994 WIPHY_VENDOR_CMD_NEED_RUNNING,
9995 .doit = wlan_hdd_cfg80211_sta_roam_policy
9996 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309997#ifdef FEATURE_WLAN_CH_AVOID
9998 {
9999 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10000 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10002 WIPHY_VENDOR_CMD_NEED_NETDEV |
10003 WIPHY_VENDOR_CMD_NEED_RUNNING,
10004 .doit = wlan_hdd_cfg80211_avoid_freq
10005 },
10006#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010007 {
10008 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010009 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10010 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10011 WIPHY_VENDOR_CMD_NEED_NETDEV |
10012 WIPHY_VENDOR_CMD_NEED_RUNNING,
10013 .doit = wlan_hdd_cfg80211_sap_configuration_set
10014 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010015 {
Peng Xu4225c152016-07-14 21:18:14 -070010016 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010017 .info.subcmd =
10018 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10019 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10020 WIPHY_VENDOR_CMD_NEED_NETDEV |
10021 WIPHY_VENDOR_CMD_NEED_RUNNING,
10022 .doit = wlan_hdd_cfg80211_p2p_lo_start
10023 },
10024 {
10025 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10026 .info.subcmd =
10027 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10028 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10029 WIPHY_VENDOR_CMD_NEED_NETDEV |
10030 WIPHY_VENDOR_CMD_NEED_RUNNING,
10031 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10032 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010033 {
10034 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10035 .info.subcmd =
10036 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10037 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10038 WIPHY_VENDOR_CMD_NEED_NETDEV |
10039 WIPHY_VENDOR_CMD_NEED_RUNNING,
10040 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10041 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010042#ifdef WLAN_FEATURE_NAN_DATAPATH
10043 {
10044 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10045 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10046 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10047 WIPHY_VENDOR_CMD_NEED_NETDEV |
10048 WIPHY_VENDOR_CMD_NEED_RUNNING,
10049 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10050 },
10051#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010052 {
10053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10056 WIPHY_VENDOR_CMD_NEED_NETDEV |
10057 WIPHY_VENDOR_CMD_NEED_RUNNING,
10058 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10059 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010060 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010061 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10062 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10063 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10064 WIPHY_VENDOR_CMD_NEED_NETDEV |
10065 WIPHY_VENDOR_CMD_NEED_RUNNING,
10066 .doit = wlan_hdd_cfg80211_get_bus_size
10067 },
10068 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010069 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10070 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10071 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10072 WIPHY_VENDOR_CMD_NEED_NETDEV |
10073 WIPHY_VENDOR_CMD_NEED_RUNNING,
10074 .doit = wlan_hdd_cfg80211_update_vendor_channel
10075 },
10076 {
bingsd09dea32017-03-17 10:08:26 +080010077 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010078 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10079 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10080 WIPHY_VENDOR_CMD_NEED_NETDEV |
10081 WIPHY_VENDOR_CMD_NEED_RUNNING,
10082 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010083 },
10084 {
10085 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10086 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10087 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10088 WIPHY_VENDOR_CMD_NEED_NETDEV |
10089 WIPHY_VENDOR_CMD_NEED_RUNNING,
10090 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010091 },
10092#ifdef WLAN_FEATURE_DISA
10093 {
10094 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10095 .info.subcmd =
10096 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10097 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10098 WIPHY_VENDOR_CMD_NEED_NETDEV |
10099 WIPHY_VENDOR_CMD_NEED_RUNNING,
10100 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10101 },
10102#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010103#ifdef FEATURE_WLAN_TDLS
10104 {
10105 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10106 .info.subcmd =
10107 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10108 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10109 WIPHY_VENDOR_CMD_NEED_NETDEV |
10110 WIPHY_VENDOR_CMD_NEED_RUNNING,
10111 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010112 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010113#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010114 {
10115 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10116 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10117 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10118 WIPHY_VENDOR_CMD_NEED_RUNNING,
10119 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10120 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010121 {
10122 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10123 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10124 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10125 WIPHY_VENDOR_CMD_NEED_NETDEV |
10126 WIPHY_VENDOR_CMD_NEED_RUNNING,
10127 .doit = wlan_hdd_cfg80211_set_trace_level
10128 },
10129
Paul Zhang3a210c52016-12-08 10:18:12 +080010130#ifdef WLAN_UMAC_CONVERGENCE
10131 COMMON_VENDOR_COMMANDS
10132#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010133 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010134};
10135
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010136#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10137 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10138 defined(FEATURE_WLAN_SCAN_PNO)
10139/**
10140 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10141 * @wiphy: pointer to wiphy
10142 * @config: pointer to config
10143 *
10144 * Return: None
10145 */
10146static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10147 struct hdd_config *config)
10148{
10149 if (config->configPNOScanSupport) {
10150 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010151 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10152 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010153 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010154 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010155 if (config->max_sched_scan_plan_interval)
10156 wiphy->max_sched_scan_plan_interval =
10157 config->max_sched_scan_plan_interval;
10158 if (config->max_sched_scan_plan_iterations)
10159 wiphy->max_sched_scan_plan_iterations =
10160 config->max_sched_scan_plan_iterations;
10161 }
10162}
10163#else
10164static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10165 struct hdd_config *config)
10166{
10167}
10168#endif
10169
10170
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010171/**
10172 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10173 * @priv_size: Size of the hdd context.
10174 *
10175 * Allocate wiphy context and hdd context.
10176 *
10177 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010178 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010179hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010180{
10181 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010182 hdd_context_t *hdd_ctx;
10183
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010184 ENTER();
10185
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010186 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10187
10188 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010189 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010190 return NULL;
10191 }
10192
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010193 hdd_ctx = wiphy_priv(wiphy);
10194
10195 hdd_ctx->wiphy = wiphy;
10196
10197 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010198}
10199
10200/*
10201 * FUNCTION: wlan_hdd_cfg80211_update_band
10202 * This function is called from the supplicant through a
10203 * private ioctl to change the band value
10204 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010205int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10206 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010207{
10208 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010209 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010210
10211 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010212 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010213
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010214 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010215 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010216
10217 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10218 struct ieee80211_supported_band *band = wiphy->bands[i];
10219
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010220 channelEnabledState = wlan_reg_get_channel_state(
10221 hdd_ctx->hdd_pdev,
10222 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010223
Dustin Browna30892e2016-10-12 17:28:36 -070010224 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010225 /* 5G only */
10226#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10227 /* Enable Social channels for P2P */
10228 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10229 (band->channels[j].center_freq)
10230 && CHANNEL_STATE_ENABLE ==
10231 channelEnabledState)
10232 band->channels[j].flags &=
10233 ~IEEE80211_CHAN_DISABLED;
10234 else
10235#endif
10236 band->channels[j].flags |=
10237 IEEE80211_CHAN_DISABLED;
10238 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010239 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010240 eCSR_BAND_24 == eBand) {
10241 /* 2G only */
10242 band->channels[j].flags |=
10243 IEEE80211_CHAN_DISABLED;
10244 continue;
10245 }
10246
Amar Singhal6842e8f2016-02-23 16:30:32 -080010247 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010248 band->channels[j].flags &=
10249 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010250 }
10251 }
10252 return 0;
10253}
10254
Peng Xuacfdda12017-02-06 16:15:38 -080010255#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010256/*
10257 * FUNCTION: wlan_hdd_cfg80211_init
10258 * This function is called by hdd_wlan_startup()
10259 * during initialization.
10260 * This function is used to initialize and register wiphy structure.
10261 */
10262int wlan_hdd_cfg80211_init(struct device *dev,
10263 struct wiphy *wiphy, struct hdd_config *pCfg)
10264{
10265 int i, j;
10266 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10267
10268 ENTER();
10269
10270 /* Now bind the underlying wlan device with wiphy */
10271 set_wiphy_dev(wiphy, dev);
10272
10273 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10274
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010275 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10276 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10277 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10278#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10279 | WIPHY_FLAG_4ADDR_STATION
10280#endif
10281 | WIPHY_FLAG_OFFCHAN_TX;
10282
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010283#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10284 wiphy->wowlan = &wowlan_support_cfg80211_init;
10285#else
10286 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10287 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10288 wiphy->wowlan.pattern_min_len = 1;
10289 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10290#endif
10291
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010292 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010293#ifdef FEATURE_WLAN_ESE
10294 || pCfg->isEseIniFeatureEnabled
10295#endif
10296 ) {
10297 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10298 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010299#ifdef FEATURE_WLAN_TDLS
10300 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10301 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10302#endif
10303
10304 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10305
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010306#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10307 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10308#endif
10309
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010310 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311
10312#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010313 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010314#endif
10315
10316 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010317 * driver can still register regulatory callback and
10318 * it will get regulatory settings in wiphy->band[], but
10319 * driver need to determine what to do with both
10320 * regulatory settings
10321 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010322
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010323#if defined QCA_WIFI_FTM
10324}
10325#endif
10326
10327 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10328
10329 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10330
10331 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10332
Arun Khandavallifae92942016-08-01 13:31:08 +053010333 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10334 | BIT(NL80211_IFTYPE_ADHOC)
10335 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10336 | BIT(NL80211_IFTYPE_P2P_GO)
10337 | BIT(NL80211_IFTYPE_AP)
10338 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010339
Arun Khandavallifae92942016-08-01 13:31:08 +053010340 if (pCfg->advertiseConcurrentOperation) {
10341 if (pCfg->enableMCC) {
10342 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010343
Arun Khandavallifae92942016-08-01 13:31:08 +053010344 for (i = 0;
10345 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10346 i++) {
10347 if (!pCfg->allowMCCGODiffBI)
10348 wlan_hdd_iface_combination[i].
10349 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010350 }
10351 }
10352 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010353 ARRAY_SIZE(wlan_hdd_iface_combination);
10354 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010355 }
10356
10357 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010358 * on ini values
10359 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010360 if (!pCfg->ShortGI20MhzEnable) {
10361 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10362 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 }
10364
10365 if (!pCfg->ShortGI40MhzEnable) {
10366 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10367 }
10368
10369 if (!pCfg->nChannelBondingMode5GHz) {
10370 wlan_hdd_band_5_ghz.ht_cap.cap &=
10371 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10372 }
10373
Abhishek Singhf512bf32016-05-04 16:47:46 +053010374 /*
10375 * In case of static linked driver at the time of driver unload,
10376 * module exit doesn't happens. Module cleanup helps in cleaning
10377 * of static memory.
10378 * If driver load happens statically, at the time of driver unload,
10379 * wiphy flags don't get reset because of static memory.
10380 * It's better not to store channel in static memory.
10381 */
Dustin Browna30892e2016-10-12 17:28:36 -070010382 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10383 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010384 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010385 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010386 hdd_err("Not enough memory to allocate channels");
10387 return -ENOMEM;
10388 }
Dustin Browna30892e2016-10-12 17:28:36 -070010389 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010390 &hdd_channels_2_4_ghz[0],
10391 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010392 if ((hdd_is_5g_supported(pHddCtx)) &&
10393 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10394 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10395 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10396 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010397 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10398 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010399 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010400 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010401 hdd_err("Not enough memory to allocate channels");
10402 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010403 bands[NL80211_BAND_2GHZ]->channels);
10404 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010405 return -ENOMEM;
10406 }
Dustin Browna30892e2016-10-12 17:28:36 -070010407 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010408 &hdd_channels_5_ghz[0],
10409 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010410 }
10411
Dustin Browna30892e2016-10-12 17:28:36 -070010412 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010413
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010414 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010415 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010416
10417 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10418 struct ieee80211_supported_band *band = wiphy->bands[i];
10419
Dustin Browna30892e2016-10-12 17:28:36 -070010420 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010421 eCSR_BAND_5G == pCfg->nBandCapability) {
10422 /* 5G only */
10423#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10424 /* Enable social channels for P2P */
10425 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10426 (band->channels[j].center_freq))
10427 band->channels[j].flags &=
10428 ~IEEE80211_CHAN_DISABLED;
10429 else
10430#endif
10431 band->channels[j].flags |=
10432 IEEE80211_CHAN_DISABLED;
10433 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010434 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010435 eCSR_BAND_24 == pCfg->nBandCapability) {
10436 /* 2G only */
10437 band->channels[j].flags |=
10438 IEEE80211_CHAN_DISABLED;
10439 continue;
10440 }
10441 }
10442 }
10443 /*Initialise the supported cipher suite details */
10444 wiphy->cipher_suites = hdd_cipher_suites;
10445 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10446
10447 /*signal strength in mBm (100*dBm) */
10448 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10449 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10450
Anurag Chouhan6d760662016-02-20 16:05:43 +053010451 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010452 wiphy->n_vendor_commands =
10453 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10454 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10455
10456 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10457 wiphy->n_vendor_events =
10458 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10459 }
10460
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010461 if (pCfg->enableDFSMasterCap) {
10462 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10463 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010464
10465 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10466
10467#ifdef QCA_HT_2040_COEX
10468 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10469#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010470 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010471
10472#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10473 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10474 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10475 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10476 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10477#endif
10478
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010479 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010480 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010481
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010482 EXIT();
10483 return 0;
10484}
10485
Abhishek Singhf512bf32016-05-04 16:47:46 +053010486/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010487 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10488 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010489 *
10490 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010491 * memory allocated in wlan_hdd_cfg80211_init also
10492 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010493 *
10494 * Return: void
10495 */
10496void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10497{
10498 int i;
10499
Dustin Browna30892e2016-10-12 17:28:36 -070010500 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010501 if (NULL != wiphy->bands[i] &&
10502 (NULL != wiphy->bands[i]->channels)) {
10503 qdf_mem_free(wiphy->bands[i]->channels);
10504 wiphy->bands[i]->channels = NULL;
10505 }
10506 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010507
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010508 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010509}
10510
Yingying Tang80e15f32016-09-27 18:23:01 +080010511/**
10512 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10513 * @hdd_ctx: HDD context
10514 *
10515 * this function will update capabilities for supported bands
10516 *
10517 * Return: void
10518 */
10519static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10520{
10521 uint32_t val32;
10522 uint16_t val16;
10523 tSirMacHTCapabilityInfo *ht_cap_info;
10524 QDF_STATUS status;
10525
10526 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10527 if (QDF_STATUS_SUCCESS != status) {
10528 hdd_err("could not get HT capability info");
10529 val32 = 0;
10530 }
10531 val16 = (uint16_t)val32;
10532 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10533
10534 if (ht_cap_info->txSTBC == true) {
10535 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10536 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10537 IEEE80211_HT_CAP_TX_STBC;
10538 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10539 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10540 IEEE80211_HT_CAP_TX_STBC;
10541 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010542
10543 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10544 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10545 vht_cap.vht_supported = 0;
10546 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10547 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10548 vht_cap.vht_supported = 0;
10549 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10550 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010551}
10552
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010553/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010554 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010555 * initialization. In wlan_hdd_cfg80211_init, only the
10556 * default values will be initialized. The final initialization
10557 * of all required members can be done here.
10558 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010559void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010560{
Yingying Tang80e15f32016-09-27 18:23:01 +080010561 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10562
10563 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010564}
10565
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010566/**
10567 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10568 * @cfg: hdd cfg
10569 *
10570 * this function update 11n mode in hdd cfg
10571 *
10572 * Return: void
10573 */
10574void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10575{
10576 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010577 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010578 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010579 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010580 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10581 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10582 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10583 cfg->sap_p2p_11ac_override = 0;
10584 }
10585 }
10586}
10587
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010588/* In this function we are registering wiphy. */
10589int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10590{
10591 ENTER();
10592 /* Register our wiphy dev with cfg80211 */
10593 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010594 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010595 return -EIO;
10596 }
10597
10598 EXIT();
10599 return 0;
10600}
10601
10602/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010603 * HDD function to update wiphy capability based on target offload status.
10604 *
10605 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10606 * capability even before downloading firmware to the target. In discrete
10607 * case, host will get know certain offload capability (say sched_scan
10608 * caps) only after downloading firmware to the target and target boots up.
10609 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10610 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010611 */
10612void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10613{
10614#ifdef FEATURE_WLAN_SCAN_PNO
10615 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10616 struct hdd_config *pCfg = pHddCtx->config;
10617
10618 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10619 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010620 * have PNO support.
10621 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010622 if (!pCfg->PnoOffload) {
10623 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10624 wiphy->max_sched_scan_ssids = 0;
10625 wiphy->max_match_sets = 0;
10626 wiphy->max_sched_scan_ie_len = 0;
10627 }
10628#endif
10629}
10630
10631/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010632#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10633
Wu Gao84d120c2017-03-24 18:46:00 +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
10642 /* Register frame indication call back */
10643 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10644
10645 /* Register for p2p ack indication */
10646 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10647
10648 /* Right now we are registering these frame when driver is getting
10649 * 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
10653 /* 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 /* WNM BSS Transition Request frame */
10674 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10675 (uint8_t *) WNM_BSS_ACTION_FRAME,
10676 WNM_BSS_ACTION_FRAME_SIZE);
10677
10678 /* WNM-Notification */
10679 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10680 (uint8_t *) WNM_NOTIFICATION_FRAME,
10681 WNM_NOTIFICATION_FRAME_SIZE);
10682}
10683#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010684void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10685{
10686 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10687 /* Register for all P2P action, public action etc frames */
10688 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10689
10690 ENTER();
10691
Abhishek Singh7996eb72015-12-30 17:24:02 +053010692 /* Register frame indication call back */
10693 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10694
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010695 /* Register for p2p ack indication */
10696 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10697
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010698 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010699 * initialized. Once we will move to 2.6.37 kernel, in which we have
10700 * frame register ops, we will move this code as a part of that
10701 */
10702
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010703 /* GAS Initial Request */
10704 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10705 (uint8_t *) GAS_INITIAL_REQ,
10706 GAS_INITIAL_REQ_SIZE);
10707
10708 /* GAS Initial Response */
10709 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10710 (uint8_t *) GAS_INITIAL_RSP,
10711 GAS_INITIAL_RSP_SIZE);
10712
10713 /* GAS Comeback Request */
10714 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10715 (uint8_t *) GAS_COMEBACK_REQ,
10716 GAS_COMEBACK_REQ_SIZE);
10717
10718 /* GAS Comeback Response */
10719 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10720 (uint8_t *) GAS_COMEBACK_RSP,
10721 GAS_COMEBACK_RSP_SIZE);
10722
10723 /* P2P Public Action */
10724 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10725 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10726 P2P_PUBLIC_ACTION_FRAME_SIZE);
10727
10728 /* P2P Action */
10729 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10730 (uint8_t *) P2P_ACTION_FRAME,
10731 P2P_ACTION_FRAME_SIZE);
10732
10733 /* WNM BSS Transition Request frame */
10734 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10735 (uint8_t *) WNM_BSS_ACTION_FRAME,
10736 WNM_BSS_ACTION_FRAME_SIZE);
10737
10738 /* WNM-Notification */
10739 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10740 (uint8_t *) WNM_NOTIFICATION_FRAME,
10741 WNM_NOTIFICATION_FRAME_SIZE);
10742}
Wu Gao84d120c2017-03-24 18:46:00 +080010743#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010744
10745void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10746{
10747 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10748 /* Register for all P2P action, public action etc frames */
10749 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10750
10751 ENTER();
10752
10753 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010754 * initialized. Once we will move to 2.6.37 kernel, in which we have
10755 * frame register ops, we will move this code as a part of that
10756 */
10757
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010758 /* GAS Initial Request */
10759
10760 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10761 (uint8_t *) GAS_INITIAL_REQ,
10762 GAS_INITIAL_REQ_SIZE);
10763
10764 /* GAS Initial Response */
10765 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10766 (uint8_t *) GAS_INITIAL_RSP,
10767 GAS_INITIAL_RSP_SIZE);
10768
10769 /* GAS Comeback Request */
10770 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10771 (uint8_t *) GAS_COMEBACK_REQ,
10772 GAS_COMEBACK_REQ_SIZE);
10773
10774 /* GAS Comeback Response */
10775 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10776 (uint8_t *) GAS_COMEBACK_RSP,
10777 GAS_COMEBACK_RSP_SIZE);
10778
10779 /* P2P Public Action */
10780 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10781 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10782 P2P_PUBLIC_ACTION_FRAME_SIZE);
10783
10784 /* P2P Action */
10785 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10786 (uint8_t *) P2P_ACTION_FRAME,
10787 P2P_ACTION_FRAME_SIZE);
10788
10789 /* WNM-Notification */
10790 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10791 (uint8_t *) WNM_NOTIFICATION_FRAME,
10792 WNM_NOTIFICATION_FRAME_SIZE);
10793}
10794
10795#ifdef FEATURE_WLAN_WAPI
10796void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10797 const uint8_t *mac_addr, const uint8_t *key,
10798 int key_Len)
10799{
10800 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10801 tCsrRoamSetKey setKey;
10802 bool isConnected = true;
10803 int status = 0;
10804 uint32_t roamId = 0xFF;
10805 uint8_t *pKeyPtr = NULL;
10806 int n = 0;
10807
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010808 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010809 hdd_device_mode_to_string(pAdapter->device_mode),
10810 pAdapter->device_mode);
10811
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010812 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010813 setKey.keyId = key_index; /* Store Key ID */
10814 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10815 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10816 setKey.paeRole = 0; /* the PAE role */
10817 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010818 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010819 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010820 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010821 }
10822 setKey.keyLength = key_Len;
10823 pKeyPtr = setKey.Key;
10824 memcpy(pKeyPtr, key, key_Len);
10825
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010826 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010827 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010828 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010829 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010830
10831 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10832 if (isConnected) {
10833 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10834 pAdapter->sessionId, &setKey, &roamId);
10835 }
10836 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010837 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010838 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10839 }
10840}
10841#endif /* FEATURE_WLAN_WAPI */
10842
10843uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10844 uint8_t eid)
10845{
10846 int left = length;
10847 uint8_t *ptr = (uint8_t *)ies_ptr;
10848 uint8_t elem_id, elem_len;
10849
10850 while (left >= 2) {
10851 elem_id = ptr[0];
10852 elem_len = ptr[1];
10853 left -= 2;
10854 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010855 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 eid, elem_len, left);
10857 return NULL;
10858 }
10859 if (elem_id == eid) {
10860 return ptr;
10861 }
10862
10863 left -= elem_len;
10864 ptr += (elem_len + 2);
10865 }
10866 return NULL;
10867}
10868
10869/*
10870 * FUNCTION: wlan_hdd_validate_operation_channel
10871 * called by wlan_hdd_cfg80211_start_bss() and
10872 * wlan_hdd_set_channel()
10873 * This function validates whether given channel is part of valid
10874 * channel list.
10875 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010876QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010877 int channel)
10878{
10879
10880 uint32_t num_ch = 0;
10881 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10882 u32 indx = 0;
10883 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10884 uint8_t fValidChannel = false, count = 0;
10885 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10886
10887 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10888
10889 if (hdd_pConfig_ini->sapAllowAllChannel) {
10890 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010891 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010892 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893 fValidChannel = true;
10894 break;
10895 }
10896 }
10897 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010898 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010899 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010900 }
10901 } else {
10902 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10903 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010904 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010905 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010906 }
10907 for (indx = 0; indx < num_ch; indx++) {
10908 if (channel == valid_ch[indx]) {
10909 break;
10910 }
10911 }
10912
10913 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010914 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010915 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916 }
10917 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010918 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010919
10920}
10921
10922#ifdef DHCP_SERVER_OFFLOAD
10923static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10924{
10925 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10926 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10927 uint8_t numEntries = 0;
10928 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10929 uint8_t num;
10930 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010931 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010932 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010933 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010934 return;
10935 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010936 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10937 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10938 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10939 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10940 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10941 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010942 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010943 goto end;
10944 }
10945 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010946 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010947 goto end;
10948 }
10949 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010950 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010951 goto end;
10952 }
10953 for (num = 0; num < numEntries; num++) {
10954 temp = srv_ip[num];
10955 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10956 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010957 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010958 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010959 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 goto end;
10961 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010962 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010963end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010964 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010965 return;
10966}
10967#endif /* DHCP_SERVER_OFFLOAD */
10968
10969static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10970 struct net_device *dev,
10971 struct bss_parameters *params)
10972{
10973 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10974 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10975 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010976 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010977
10978 ENTER();
10979
Anurag Chouhan6d760662016-02-20 16:05:43 +053010980 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010981 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010982 return -EINVAL;
10983 }
10984
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010985 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10986 hdd_err("invalid session id: %d", pAdapter->sessionId);
10987 return -EINVAL;
10988 }
10989
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010990 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010991 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10992 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010993 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010994 hdd_device_mode_to_string(pAdapter->device_mode),
10995 pAdapter->device_mode, params->ap_isolate);
10996
10997 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10998 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010999 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011000 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011001
Krunal Sonib4326f22016-03-10 13:05:51 -080011002 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11003 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011004 return -EOPNOTSUPP;
11005 }
11006
11007 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011008 * want to update this parameter
11009 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011010 if (-1 != params->ap_isolate) {
11011 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11012 !!params->ap_isolate;
11013
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011014 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011015 pAdapter->sessionId,
11016 pAdapter->sessionCtx.
11017 ap.
11018 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011019 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011020 ret = -EINVAL;
11021 }
11022 }
11023
11024 EXIT();
11025 return ret;
11026}
11027
Krunal Soni8c37e322016-02-03 16:08:37 -080011028/**
11029 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11030 * @ndev: pointer to net device provided by supplicant
11031 * @type: type of the interface, upper layer wanted to change
11032 *
11033 * Upper layer provides the new interface mode that needs to be changed
11034 * for given net device
11035 *
11036 * Return: success or failure in terms of integer value
11037 */
11038static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011039 enum nl80211_iftype type)
11040{
Krunal Soni8c37e322016-02-03 16:08:37 -080011041 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11042 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11043 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011044 hdd_wext_state_t *wext;
11045 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011046 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011047
11048 ENTER();
11049
Krunal Soni8c37e322016-02-03 16:08:37 -080011050 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011051 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052 return 0;
11053 }
11054
11055 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011056 hdd_stop_adapter(hdd_ctx, adapter, true);
11057 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011058 wdev->iftype = type;
11059 /*Check for sub-string p2p to confirm its a p2p interface */
11060 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011061 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011062 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011063 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011064 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011065 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011066 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011067 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011068 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011069 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011070 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011071 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11072 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011073 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11074 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011075 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011076 adapter->scan_info.scanAddIE.length;
11077 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011078 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011079 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11080 wext->roamProfile.phyMode =
11081 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11082 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011083 EXIT();
11084 return status;
11085}
11086
11087static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11088 struct net_device *dev,
11089 struct bss_parameters *params)
11090{
11091 int ret;
11092
11093 cds_ssr_protect(__func__);
11094 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11095 cds_ssr_unprotect(__func__);
11096
11097 return ret;
11098}
11099
11100/* FUNCTION: wlan_hdd_change_country_code_cd
11101 * to wait for contry code completion
11102 */
11103void *wlan_hdd_change_country_code_cb(void *pAdapter)
11104{
11105 hdd_adapter_t *call_back_pAdapter = pAdapter;
11106 complete(&call_back_pAdapter->change_country_code);
11107 return NULL;
11108}
11109
Rajeev Kumar98edb772016-01-19 12:42:19 -080011110/**
11111 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11112 * @wiphy: Pointer to the wiphy structure
11113 * @ndev: Pointer to the net device
11114 * @type: Interface type
11115 * @flags: Flags for change interface
11116 * @params: Pointer to change interface parameters
11117 *
11118 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011119 */
11120static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11121 struct net_device *ndev,
11122 enum nl80211_iftype type,
11123 u32 *flags,
11124 struct vif_params *params)
11125{
11126 struct wireless_dev *wdev;
11127 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11128 hdd_context_t *pHddCtx;
11129 tCsrRoamProfile *pRoamProfile = NULL;
11130 eCsrRoamBssType LastBSSType;
11131 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011132 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011133 int status;
11134
11135 ENTER();
11136
Anurag Chouhan6d760662016-02-20 16:05:43 +053011137 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011138 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011139 return -EINVAL;
11140 }
11141
11142 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11143 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011144 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011145 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011146
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011147 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011148 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11149 pAdapter->sessionId, type));
11150
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011151 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152 pAdapter->device_mode, type);
11153
Arun Khandavallifae92942016-08-01 13:31:08 +053011154 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11155 if (status) {
11156 hdd_err("Failed to start modules");
11157 return -EINVAL;
11158 }
11159
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011160 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011161 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11162 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011163 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011164 return -EINVAL;
11165 }
11166
11167 pConfig = pHddCtx->config;
11168 wdev = ndev->ieee80211_ptr;
11169
11170 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011171 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11172 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011173
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011174 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011175 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011176 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11177 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11178 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11179 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180 hdd_wext_state_t *pWextState =
11181 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11182
11183 pRoamProfile = &pWextState->roamProfile;
11184 LastBSSType = pRoamProfile->BSSType;
11185
11186 switch (type) {
11187 case NL80211_IFTYPE_STATION:
11188 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011189 case NL80211_IFTYPE_ADHOC:
11190 if (type == NL80211_IFTYPE_ADHOC) {
11191 wlan_hdd_tdls_exit(pAdapter);
11192 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011193 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011194 }
11195 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11196 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011197 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011198 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011199 if (hdd_start_adapter(pAdapter)) {
11200 hdd_err("Failed to start adapter :%d",
11201 pAdapter->device_mode);
11202 return -EINVAL;
11203 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011204 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205 case NL80211_IFTYPE_AP:
11206 case NL80211_IFTYPE_P2P_GO:
11207 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011208 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011209 (type ==
11210 NL80211_IFTYPE_AP) ? "SoftAP" :
11211 "P2pGo");
11212
11213 /* Cancel any remain on channel for GO mode */
11214 if (NL80211_IFTYPE_P2P_GO == type) {
11215 wlan_hdd_cancel_existing_remain_on_channel
11216 (pAdapter);
11217 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011218
Arun Khandavallifae92942016-08-01 13:31:08 +053011219 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011220 /* De-init the adapter */
11221 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11222 memset(&pAdapter->sessionCtx, 0,
11223 sizeof(pAdapter->sessionCtx));
11224 pAdapter->device_mode =
11225 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011226 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11227 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011228
11229 /*
11230 * Fw will take care incase of concurrency
11231 */
11232
Krunal Sonib4326f22016-03-10 13:05:51 -080011233 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011234 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011235 /* To meet Android requirements create
11236 * a randomized MAC address of the
11237 * form 02:1A:11:Fx:xx:xx
11238 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011239 get_random_bytes(&ndev->dev_addr[3], 3);
11240 ndev->dev_addr[0] = 0x02;
11241 ndev->dev_addr[1] = 0x1A;
11242 ndev->dev_addr[2] = 0x11;
11243 ndev->dev_addr[3] |= 0xF0;
11244 memcpy(pAdapter->macAddressCurrent.
11245 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011246 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011247 pr_info("wlan: Generated HotSpot BSSID "
11248 MAC_ADDRESS_STR "\n",
11249 MAC_ADDR_ARRAY(ndev->dev_addr));
11250 }
11251
11252 hdd_set_ap_ops(pAdapter->dev);
11253
Arun Khandavallifae92942016-08-01 13:31:08 +053011254 if (hdd_start_adapter(pAdapter)) {
11255 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011256 return -EINVAL;
11257 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258 /* Interface type changed update in wiphy structure */
11259 if (wdev) {
11260 wdev->iftype = type;
11261 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011262 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011263 return -EINVAL;
11264 }
11265 goto done;
11266 }
11267
11268 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011269 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270 return -EOPNOTSUPP;
11271 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011272 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11273 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011274 switch (type) {
11275 case NL80211_IFTYPE_STATION:
11276 case NL80211_IFTYPE_P2P_CLIENT:
11277 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011278 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11279 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011280 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011281 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011282 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011283 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011284 pAdapter->device_mode);
11285 return -EINVAL;
11286 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 goto done;
11288
11289 case NL80211_IFTYPE_AP:
11290 case NL80211_IFTYPE_P2P_GO:
11291 wdev->iftype = type;
11292 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011293 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011294 goto done;
11295
11296 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011297 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011298 return -EOPNOTSUPP;
11299 }
11300 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011301 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011302 pAdapter->device_mode);
11303 return -EOPNOTSUPP;
11304 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011305done:
11306 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011307 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11308 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011309
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011310 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011311
11312 EXIT();
11313 return 0;
11314}
11315
Rajeev Kumar98edb772016-01-19 12:42:19 -080011316/**
11317 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11318 * @wiphy: Pointer to the wiphy structure
11319 * @ndev: Pointer to the net device
11320 * @type: Interface type
11321 * @flags: Flags for change interface
11322 * @params: Pointer to change interface parameters
11323 *
11324 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011325 */
11326static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11327 struct net_device *ndev,
11328 enum nl80211_iftype type,
11329 u32 *flags,
11330 struct vif_params *params)
11331{
11332 int ret;
11333
11334 cds_ssr_protect(__func__);
11335 ret =
11336 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11337 cds_ssr_unprotect(__func__);
11338
11339 return ret;
11340}
11341
Frank Liud4b2fa02017-03-29 11:46:48 +080011342#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011343static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11344 int index, uint8_t match)
11345{
11346 int i;
11347 for (i = 0; i < index; i++) {
11348 if (arr[i] == match)
11349 return true;
11350 }
11351 return false;
11352}
11353#endif
11354
11355/**
11356 * __wlan_hdd_change_station() - change station
11357 * @wiphy: Pointer to the wiphy structure
11358 * @dev: Pointer to the net device.
11359 * @mac: bssid
11360 * @params: Pointer to station parameters
11361 *
11362 * Return: 0 for success, error number on failure.
11363 */
11364#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11365static int __wlan_hdd_change_station(struct wiphy *wiphy,
11366 struct net_device *dev,
11367 const uint8_t *mac,
11368 struct station_parameters *params)
11369#else
11370static int __wlan_hdd_change_station(struct wiphy *wiphy,
11371 struct net_device *dev,
11372 uint8_t *mac,
11373 struct station_parameters *params)
11374#endif
11375{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011376 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11378 hdd_context_t *pHddCtx;
11379 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011380 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011381#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382 tCsrStaParams StaParams = { 0 };
11383 uint8_t isBufSta = 0;
11384 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011385 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011386#endif
11387 int ret;
11388
11389 ENTER();
11390
Anurag Chouhan6d760662016-02-20 16:05:43 +053011391 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011392 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011393 return -EINVAL;
11394 }
11395
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011396 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011397 TRACE_CODE_HDD_CHANGE_STATION,
11398 pAdapter->sessionId, params->listen_interval));
11399
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011400 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11401 hdd_err("invalid session id: %d", pAdapter->sessionId);
11402 return -EINVAL;
11403 }
11404
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011405 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11406 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011407 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011408 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011409
11410 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11411
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011412 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011413
Krunal Sonib4326f22016-03-10 13:05:51 -080011414 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11415 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011416 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11417 status =
11418 hdd_softap_change_sta_state(pAdapter,
11419 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011420 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011421
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011422 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011423 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011424 return -EINVAL;
11425 }
11426 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011427 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11428 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011429 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011430#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11431 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11432 dev, mac, params);
11433#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011434
11435 if (cds_is_sub_20_mhz_enabled()) {
11436 hdd_err("TDLS not allowed with sub 20 MHz");
11437 return -EINVAL;
11438 }
11439
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011440 StaParams.capability = params->capability;
11441 StaParams.uapsd_queues = params->uapsd_queues;
11442 StaParams.max_sp = params->max_sp;
11443
11444 /* Convert (first channel , number of channels) tuple to
11445 * the total list of channels. This goes with the assumption
11446 * that if the first channel is < 14, then the next channels
11447 * are an incremental of 1 else an incremental of 4 till the number
11448 * of channels.
11449 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011450 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011451 if (0 != params->supported_channels_len) {
11452 int i = 0, j = 0, k = 0, no_of_channels = 0;
11453 int num_unique_channels;
11454 int next;
11455 for (i = 0;
11456 i < params->supported_channels_len
11457 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11458 int wifi_chan_index;
11459 if (!wlan_hdd_is_duplicate_channel
11460 (StaParams.supported_channels, j,
11461 params->supported_channels[i])) {
11462 StaParams.
11463 supported_channels[j] =
11464 params->
11465 supported_channels[i];
11466 } else {
11467 continue;
11468 }
11469 wifi_chan_index =
11470 ((StaParams.supported_channels[j] <=
11471 HDD_CHANNEL_14) ? 1 : 4);
11472 no_of_channels =
11473 params->supported_channels[i + 1];
11474
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011475 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 -080011476 StaParams.
11477 supported_channels[j],
11478 wifi_chan_index,
11479 no_of_channels);
11480 for (k = 1; k <= no_of_channels &&
11481 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11482 k++) {
11483 next =
11484 StaParams.
11485 supported_channels[j] +
11486 wifi_chan_index;
11487 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11488 StaParams.
11489 supported_channels[j
11490 +
11491 1]
11492 = next;
11493 } else {
11494 continue;
11495 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011496 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011497 j + 1,
11498 StaParams.
11499 supported_channels[j +
11500 1]);
11501 j += 1;
11502 }
11503 }
11504 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011505 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011506 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011507 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011508 StaParams.
11509 supported_channels[i]);
11510 }
11511 if (MAX_CHANNEL < num_unique_channels)
11512 num_unique_channels = MAX_CHANNEL;
11513 StaParams.supported_channels_len =
11514 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011515 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011516 StaParams.supported_channels_len);
11517 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011518 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011519 params->supported_oper_classes,
11520 params->supported_oper_classes_len);
11521 StaParams.supported_oper_classes_len =
11522 params->supported_oper_classes_len;
11523
11524 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011525 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526 params->ext_capab,
11527 sizeof(StaParams.extn_capability));
11528
11529 if (NULL != params->ht_capa) {
11530 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011531 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011532 sizeof(tSirHTCap));
11533 }
11534
11535 StaParams.supported_rates_len =
11536 params->supported_rates_len;
11537
11538 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11539 * The supported_rates array , for all the structures propogating till Add Sta
11540 * to the firmware has to be modified , if the supplicant (ieee80211) is
11541 * modified to send more rates.
11542 */
11543
11544 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11545 */
11546 if (StaParams.supported_rates_len >
11547 SIR_MAC_MAX_SUPP_RATES)
11548 StaParams.supported_rates_len =
11549 SIR_MAC_MAX_SUPP_RATES;
11550
11551 if (0 != StaParams.supported_rates_len) {
11552 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011553 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011554 params->supported_rates,
11555 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011556 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557 StaParams.supported_rates_len);
11558 for (i = 0; i < StaParams.supported_rates_len;
11559 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011560 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011561 StaParams.supported_rates[i]);
11562 }
11563
11564 if (NULL != params->vht_capa) {
11565 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011566 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567 params->vht_capa,
11568 sizeof(tSirVHTCap));
11569 }
11570
11571 if (0 != params->ext_capab_len) {
11572 /*Define A Macro : TODO Sunil */
11573 if ((1 << 4) & StaParams.extn_capability[3]) {
11574 isBufSta = 1;
11575 }
11576 /* TDLS Channel Switching Support */
11577 if ((1 << 6) & StaParams.extn_capability[3]) {
11578 isOffChannelSupported = 1;
11579 }
11580 }
11581
Nitesh Shah99934ac2016-09-05 15:54:08 +053011582 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011583 (params->ht_capa || params->vht_capa ||
11584 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011585 is_qos_wmm_sta = true;
11586
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011587 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011588 " is_qos_wmm_sta= %d HTcapPresent = %d",
11589 __func__, is_qos_wmm_sta,
11590 StaParams.htcap_present);
11591
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011592 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011593 &StaParams,
11594 isBufSta,
11595 isOffChannelSupported,
11596 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011597 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011598 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011599 return -EINVAL;
11600 }
11601
11602 status =
11603 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11604 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011605 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011606 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011607 return -EINVAL;
11608 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011610 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011611 }
11612 EXIT();
11613 return ret;
11614}
11615
11616/**
11617 * wlan_hdd_change_station() - cfg80211 change station handler function
11618 * @wiphy: Pointer to the wiphy structure
11619 * @dev: Pointer to the net device.
11620 * @mac: bssid
11621 * @params: Pointer to station parameters
11622 *
11623 * This is the cfg80211 change station handler function which invokes
11624 * the internal function @__wlan_hdd_change_station with
11625 * SSR protection.
11626 *
11627 * Return: 0 for success, error number on failure.
11628 */
11629#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11630static int wlan_hdd_change_station(struct wiphy *wiphy,
11631 struct net_device *dev,
11632 const u8 *mac,
11633 struct station_parameters *params)
11634#else
11635static int wlan_hdd_change_station(struct wiphy *wiphy,
11636 struct net_device *dev,
11637 u8 *mac,
11638 struct station_parameters *params)
11639#endif
11640{
11641 int ret;
11642
11643 cds_ssr_protect(__func__);
11644 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11645 cds_ssr_unprotect(__func__);
11646
11647 return ret;
11648}
11649
11650/*
11651 * FUNCTION: __wlan_hdd_cfg80211_add_key
11652 * This function is used to initialize the key information
11653 */
11654static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11655 struct net_device *ndev,
11656 u8 key_index, bool pairwise,
11657 const u8 *mac_addr,
11658 struct key_params *params)
11659{
11660 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11661 tCsrRoamSetKey setKey;
11662 int status;
11663 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011665 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011666 hdd_context_t *pHddCtx;
11667 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11668
11669 ENTER();
11670
Anurag Chouhan6d760662016-02-20 16:05:43 +053011671 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011672 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011673 return -EINVAL;
11674 }
11675
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011676 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011677 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011678 return -EINVAL;
11679 }
11680
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011681 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011682 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11683 pAdapter->sessionId, params->key_len));
11684 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11685 status = wlan_hdd_validate_context(pHddCtx);
11686
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011687 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011688 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011689
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011690 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691 hdd_device_mode_to_string(pAdapter->device_mode),
11692 pAdapter->device_mode);
11693
11694 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011695 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011696
11697 return -EINVAL;
11698 }
11699
11700 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011701 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011702
11703 return -EINVAL;
11704 }
11705
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011706 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011707
11708 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011709 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011710 setKey.keyId = key_index;
11711 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011712 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713
11714 switch (params->cipher) {
11715 case WLAN_CIPHER_SUITE_WEP40:
11716 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11717 break;
11718
11719 case WLAN_CIPHER_SUITE_WEP104:
11720 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11721 break;
11722
11723 case WLAN_CIPHER_SUITE_TKIP:
11724 {
11725 u8 *pKey = &setKey.Key[0];
11726 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11727
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011728 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011729
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011730 /* Supplicant sends the 32bytes key in this order
11731 *
11732 * |--------------|----------|----------|
11733 * | Tk1 |TX-MIC | RX Mic |
11734 * |--------------|----------|----------|
11735 * <---16bytes---><--8bytes--><--8bytes-->
11736 *
11737 * Sme expects the 32 bytes key to be in the below order
11738 *
11739 * |--------------|----------|----------|
11740 * | Tk1 |RX-MIC | TX Mic |
11741 * |--------------|----------|----------|
11742 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011743 */
11744 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011745 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011746
11747 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011748 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011749
11750 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011751 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752
11753 break;
11754 }
11755
11756 case WLAN_CIPHER_SUITE_CCMP:
11757 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11758 break;
11759
11760#ifdef FEATURE_WLAN_WAPI
11761 case WLAN_CIPHER_SUITE_SMS4:
11762 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011763 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011764 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11765 mac_addr, params->key,
11766 params->key_len);
11767 return 0;
11768 }
11769#endif
11770
11771#ifdef FEATURE_WLAN_ESE
11772 case WLAN_CIPHER_SUITE_KRK:
11773 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11774 break;
11775#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11776 case WLAN_CIPHER_SUITE_BTK:
11777 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11778 break;
11779#endif
11780#endif
11781
11782#ifdef WLAN_FEATURE_11W
11783 case WLAN_CIPHER_SUITE_AES_CMAC:
11784 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11785 break;
11786#endif
11787
11788 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011789 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011790 return -EOPNOTSUPP;
11791 }
11792
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011793 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011794
11795 if (!pairwise) {
11796 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011797 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011798 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011799 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011800 } else {
11801 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011802 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011803 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011804 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011805 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011806 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011807 /* if a key is already installed, block all subsequent ones */
11808 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011809 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011810 return 0;
11811 }
11812
11813 setKey.keyDirection = eSIR_TX_RX;
11814 /*Set the group key */
11815 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11816 pAdapter->sessionId, &setKey, &roamId);
11817
11818 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011819 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011820 return -EINVAL;
11821 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011822 /* Save the keys here and call sme_roam_set_key for setting
11823 * the PTK after peer joins the IBSS network
11824 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011825 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 &setKey, sizeof(tCsrRoamSetKey));
11827
11828 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11829 return status;
11830 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011831 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11832 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011833 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11834 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011835 status = wlansap_set_key_sta(
11836 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011837 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011838 hdd_err("wlansap_set_key_sta failed status: %d",
11839 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011840 }
11841 }
11842
11843 /* Save the key in ap ctx for use on START_BASS and restart */
11844 if (pairwise ||
11845 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11846 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011847 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848 sizeof(tCsrRoamSetKey));
11849 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011850 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011851 sizeof(tCsrRoamSetKey));
11852
Krunal Sonib4326f22016-03-10 13:05:51 -080011853 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11854 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011855 hdd_wext_state_t *pWextState =
11856 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11857 hdd_station_ctx_t *pHddStaCtx =
11858 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11859
11860 if (!pairwise) {
11861 /* set group key */
11862 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011863 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011864 __func__, __LINE__);
11865 hdd_perform_roam_set_key_complete(pAdapter);
11866 }
11867 }
11868
11869 pWextState->roamProfile.Keys.KeyLength[key_index] =
11870 (u8) params->key_len;
11871
11872 pWextState->roamProfile.Keys.defaultIndex = key_index;
11873
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011874 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011875 KeyMaterial[key_index][0], params->key,
11876 params->key_len);
11877
11878 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11879
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011880 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011881 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11882 setKey.keyDirection);
11883
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011884 /* The supplicant may attempt to set the PTK once
11885 * pre-authentication is done. Save the key in the
11886 * UMAC and include it in the ADD BSS request
11887 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011888 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011889 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011890 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011891 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011892 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011893 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011894 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011895 return -EINVAL;
11896 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011897
11898 /* issue set key request to SME */
11899 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11900 pAdapter->sessionId, &setKey, &roamId);
11901
11902 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011903 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011904 pHddStaCtx->roam_info.roamingState =
11905 HDD_ROAM_STATE_NONE;
11906 return -EINVAL;
11907 }
11908
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011909 /* in case of IBSS as there was no information
11910 * available about WEP keys during IBSS join, group
11911 * key intialized with NULL key, so re-initialize
11912 * group key with correct value
11913 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011914 if ((eCSR_BSS_TYPE_START_IBSS ==
11915 pWextState->roamProfile.BSSType)
11916 &&
11917 !((IW_AUTH_KEY_MGMT_802_1X ==
11918 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11919 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11920 pHddStaCtx->conn_info.authType)
11921 )
11922 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11923 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11924 )
11925 ) {
11926 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011927 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011928
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011929 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011930 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11931 setKey.keyDirection);
11932
11933 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11934 pAdapter->sessionId, &setKey,
11935 &roamId);
11936
11937 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011938 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011939 pHddStaCtx->roam_info.roamingState =
11940 HDD_ROAM_STATE_NONE;
11941 return -EINVAL;
11942 }
11943 }
11944 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011945 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011946 return 0;
11947}
11948
11949static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11950 struct net_device *ndev,
11951 u8 key_index, bool pairwise,
11952 const u8 *mac_addr,
11953 struct key_params *params)
11954{
11955 int ret;
11956 cds_ssr_protect(__func__);
11957 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11958 mac_addr, params);
11959 cds_ssr_unprotect(__func__);
11960
11961 return ret;
11962}
11963
11964/*
11965 * FUNCTION: __wlan_hdd_cfg80211_get_key
11966 * This function is used to get the key information
11967 */
11968static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11969 struct net_device *ndev,
11970 u8 key_index, bool pairwise,
11971 const u8 *mac_addr, void *cookie,
11972 void (*callback)(void *cookie,
11973 struct key_params *)
11974 )
11975{
11976 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11977 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11978 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11979 struct key_params params;
11980
11981 ENTER();
11982
Anurag Chouhan6d760662016-02-20 16:05:43 +053011983 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011984 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011985 return -EINVAL;
11986 }
11987
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011988 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011989 hdd_device_mode_to_string(pAdapter->device_mode),
11990 pAdapter->device_mode);
11991
11992 memset(&params, 0, sizeof(params));
11993
11994 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011995 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011996 return -EINVAL;
11997 }
11998
11999 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12000 case eCSR_ENCRYPT_TYPE_NONE:
12001 params.cipher = IW_AUTH_CIPHER_NONE;
12002 break;
12003
12004 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12005 case eCSR_ENCRYPT_TYPE_WEP40:
12006 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12007 break;
12008
12009 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12010 case eCSR_ENCRYPT_TYPE_WEP104:
12011 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12012 break;
12013
12014 case eCSR_ENCRYPT_TYPE_TKIP:
12015 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12016 break;
12017
12018 case eCSR_ENCRYPT_TYPE_AES:
12019 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12020 break;
12021
12022 default:
12023 params.cipher = IW_AUTH_CIPHER_NONE;
12024 break;
12025 }
12026
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012027 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012028 TRACE_CODE_HDD_CFG80211_GET_KEY,
12029 pAdapter->sessionId, params.cipher));
12030
12031 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12032 params.seq_len = 0;
12033 params.seq = NULL;
12034 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12035 callback(cookie, &params);
12036
12037 EXIT();
12038 return 0;
12039}
12040
12041static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12042 struct net_device *ndev,
12043 u8 key_index, bool pairwise,
12044 const u8 *mac_addr, void *cookie,
12045 void (*callback)(void *cookie,
12046 struct key_params *)
12047 )
12048{
12049 int ret;
12050
12051 cds_ssr_protect(__func__);
12052 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12053 mac_addr, cookie, callback);
12054 cds_ssr_unprotect(__func__);
12055
12056 return ret;
12057}
12058
12059/**
12060 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12061 * @wiphy: wiphy interface context
12062 * @ndev: pointer to net device
12063 * @key_index: Key index used in 802.11 frames
12064 * @unicast: true if it is unicast key
12065 * @multicast: true if it is multicast key
12066 *
12067 * This function is required for cfg80211_ops API.
12068 * It is used to delete the key information
12069 * Underlying hardware implementation does not have API to delete the
12070 * encryption key. It is automatically deleted when the peer is
12071 * removed. Hence this function currently does nothing.
12072 * Future implementation may interprete delete key operation to
12073 * replacing the key with a random junk value, effectively making it
12074 * useless.
12075 *
12076 * Return: status code, always 0.
12077 */
12078
12079static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12080 struct net_device *ndev,
12081 u8 key_index,
12082 bool pairwise, const u8 *mac_addr)
12083{
12084 EXIT();
12085 return 0;
12086}
12087
12088/**
12089 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12090 * @wiphy: Pointer to wiphy structure.
12091 * @dev: Pointer to net_device structure.
12092 * @key_index: key index
12093 * @pairwise: pairwise
12094 * @mac_addr: mac address
12095 *
12096 * This is the cfg80211 delete key handler function which invokes
12097 * the internal function @__wlan_hdd_cfg80211_del_key with
12098 * SSR protection.
12099 *
12100 * Return: 0 for success, error number on failure.
12101 */
12102static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12103 struct net_device *dev,
12104 u8 key_index,
12105 bool pairwise, const u8 *mac_addr)
12106{
12107 int ret;
12108
12109 cds_ssr_protect(__func__);
12110 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12111 pairwise, mac_addr);
12112 cds_ssr_unprotect(__func__);
12113
12114 return ret;
12115}
12116
12117/*
12118 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12119 * This function is used to set the default tx key index
12120 */
12121static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12122 struct net_device *ndev,
12123 u8 key_index,
12124 bool unicast, bool multicast)
12125{
12126 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12127 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12128 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12129 hdd_context_t *pHddCtx;
12130 int status;
12131
12132 ENTER();
12133
Anurag Chouhan6d760662016-02-20 16:05:43 +053012134 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012135 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012136 return -EINVAL;
12137 }
12138
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012139 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012140 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012141 return -EINVAL;
12142 }
12143
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012144 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012145 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12146 pAdapter->sessionId, key_index));
12147
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012148 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012149 hdd_device_mode_to_string(pAdapter->device_mode),
12150 pAdapter->device_mode, key_index);
12151
12152 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012153 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012154 return -EINVAL;
12155 }
12156
12157 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12158 status = wlan_hdd_validate_context(pHddCtx);
12159
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012160 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012161 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012162
Krunal Sonib4326f22016-03-10 13:05:51 -080012163 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12164 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012165 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12166 pHddStaCtx->conn_info.ucEncryptionType) &&
12167 (eCSR_ENCRYPT_TYPE_AES !=
12168 pHddStaCtx->conn_info.ucEncryptionType)) {
12169 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012170 * then update the default key index
12171 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012172
12173 tCsrRoamSetKey setKey;
12174 uint32_t roamId = 0xFF;
12175 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12176
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012177 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012178
12179 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012180 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012181 setKey.keyId = key_index;
12182 setKey.keyLength = Keys->KeyLength[key_index];
12183
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012184 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012185 &Keys->KeyMaterial[key_index][0],
12186 Keys->KeyLength[key_index]);
12187
12188 setKey.keyDirection = eSIR_TX_RX;
12189
Anurag Chouhanc5548422016-02-24 18:33:27 +053012190 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012191 &pHddStaCtx->conn_info.bssId);
12192
12193 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12194 pWextState->roamProfile.EncryptionType.
12195 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012196 /* In the case of dynamic wep
12197 * supplicant hardcodes DWEP type to
12198 * eCSR_ENCRYPT_TYPE_WEP104 even
12199 * though ap is configured for WEP-40
12200 * encryption. In this canse the key
12201 * length is 5 but the encryption type
12202 * is 104 hence checking the key
12203 * lenght(5) and encryption type(104)
12204 * and switching encryption type to 40
12205 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012206 pWextState->roamProfile.EncryptionType.
12207 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12208 pWextState->roamProfile.mcEncryptionType.
12209 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12210 }
12211
12212 setKey.encType =
12213 pWextState->roamProfile.EncryptionType.
12214 encryptionType[0];
12215
12216 /* Issue set key request */
12217 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12218 pAdapter->sessionId, &setKey,
12219 &roamId);
12220
12221 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012222 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012223 status);
12224 return -EINVAL;
12225 }
12226 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012227 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012228 /* In SoftAp mode setting key direction for default mode */
12229 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12230 pWextState->roamProfile.EncryptionType.encryptionType[0])
12231 && (eCSR_ENCRYPT_TYPE_AES !=
12232 pWextState->roamProfile.EncryptionType.
12233 encryptionType[0])) {
12234 /* Saving key direction for default key index to TX default */
12235 hdd_ap_ctx_t *pAPCtx =
12236 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12237 pAPCtx->wepKey[key_index].keyDirection =
12238 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012239 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012240 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012241 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012242 }
12243 }
12244
12245 EXIT();
12246 return status;
12247}
12248
12249static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12250 struct net_device *ndev,
12251 u8 key_index,
12252 bool unicast, bool multicast)
12253{
12254 int ret;
12255 cds_ssr_protect(__func__);
12256 ret =
12257 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12258 multicast);
12259 cds_ssr_unprotect(__func__);
12260
12261 return ret;
12262}
12263
Abhishek Singhc9941602016-08-09 16:06:22 +053012264/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012265 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12266 * interface that BSS might have been lost.
12267 * @pAdapter: adaptor
12268 * @bssid: bssid which might have been lost
12269 *
12270 * Return: bss which is unlinked from kernel cache
12271 */
12272struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12273 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012274{
12275 struct net_device *dev = pAdapter->dev;
12276 struct wireless_dev *wdev = dev->ieee80211_ptr;
12277 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278 struct cfg80211_bss *bss = NULL;
12279
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012280 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012281 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012282 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012283 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012284 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012285 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012286 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012287 cfg80211_unlink_bss(wiphy, bss);
12288 }
12289 return bss;
12290}
12291
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012292#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12293 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12294static struct cfg80211_bss *
12295wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12296 struct ieee80211_channel *chan,
12297 struct ieee80211_mgmt *mgmt,
12298 size_t frame_len,
12299 int rssi, gfp_t gfp,
12300 uint64_t boottime_ns)
12301{
12302 struct cfg80211_bss *bss_status = NULL;
12303 struct cfg80211_inform_bss data = {0};
12304
12305 data.chan = chan;
12306 data.boottime_ns = boottime_ns;
12307 data.signal = rssi;
12308 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12309 frame_len, gfp);
12310 return bss_status;
12311}
12312#else
12313static struct cfg80211_bss *
12314wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12315 struct ieee80211_channel *chan,
12316 struct ieee80211_mgmt *mgmt,
12317 size_t frame_len,
12318 int rssi, gfp_t gfp,
12319 uint64_t boottime_ns)
12320{
12321 struct cfg80211_bss *bss_status = NULL;
12322
12323 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12324 rssi, gfp);
12325 return bss_status;
12326}
12327#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012328
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329/**
12330 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12331 * @pAdapter: Pointer to adapter
12332 * @bss_desc: Pointer to bss descriptor
12333 *
12334 * This function is used to inform the BSS details to nl80211 interface.
12335 *
12336 * Return: struct cfg80211_bss pointer
12337 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012338struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12339 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012340{
12341 /*
12342 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12343 * already exists in bss data base of cfg80211 for that particular BSS
12344 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12345 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12346 * As of now there is no possibility to get the mgmt(probe response)
12347 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12348 * and passing to cfg80211_inform_bss_frame.
12349 */
12350 struct net_device *dev = pAdapter->dev;
12351 struct wireless_dev *wdev = dev->ieee80211_ptr;
12352 struct wiphy *wiphy = wdev->wiphy;
12353 int chan_no = bss_desc->channelId;
12354#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12355 qcom_ie_age *qie_age = NULL;
12356 int ie_length =
12357 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12358#else
12359 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12360#endif
12361 const char *ie =
12362 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12363 unsigned int freq;
12364 struct ieee80211_channel *chan;
12365 struct ieee80211_mgmt *mgmt = NULL;
12366 struct cfg80211_bss *bss_status = NULL;
12367 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12368 int rssi = 0;
12369 hdd_context_t *pHddCtx;
12370 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012371 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012372 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373
12374 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12375 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012376 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012377 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012378
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012379 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012380 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012381 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012382 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012383 return NULL;
12384 }
12385
12386 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012388 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012389 * Instead it wants a monotonic increasing value
12390 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012391 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012392 mgmt->u.probe_resp.timestamp =
12393 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012394
12395 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12396 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12397
12398#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12399 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12400 /* Assuming this is the last IE, copy at the end */
12401 ie_length -= sizeof(qcom_ie_age);
12402 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12403 qie_age->element_id = QCOM_VENDOR_IE_ID;
12404 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12405 qie_age->oui_1 = QCOM_OUI1;
12406 qie_age->oui_2 = QCOM_OUI2;
12407 qie_age->oui_3 = QCOM_OUI3;
12408 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012409 /*
12410 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12411 * all bss related timestamp is in units of ms. Due to this when scan
12412 * results are sent to lowi the scan age is high.To address this,
12413 * send age in units of 1/10 ms.
12414 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012415 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012416 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012417 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012418 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12419 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012420 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12421 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012422#endif
12423
12424 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12425 if (bss_desc->fProbeRsp) {
12426 mgmt->frame_control |=
12427 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12428 } else {
12429 mgmt->frame_control |=
12430 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12431 }
12432
12433 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012434 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012435 freq =
12436 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012437 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012438 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012439 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012440 freq =
12441 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012442 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012443 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012444 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012445 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012446 return NULL;
12447 }
12448
12449 chan = __ieee80211_get_channel(wiphy, freq);
12450 /* When the band is changed on the fly using the GUI, three things are done
12451 * 1. scan abort
12452 * 2. flush scan results from cache
12453 * 3. update the band with the new band user specified (refer to the
12454 * hdd_set_band_helper function) as part of the scan abort, message will be
12455 * queued to PE and we proceed with flushing and changinh the band.
12456 * PE will stop the scanning further and report back the results what ever
12457 * it had till now by calling the call back function.
12458 * if the time between update band and scandone call back is sufficient
12459 * enough the band change reflects in SME, SME validates the channels
12460 * and discards the channels correponding to previous band and calls back
12461 * with zero bss results. but if the time between band update and scan done
12462 * callback is very small then band change will not reflect in SME and SME
12463 * reports to HDD all the channels correponding to previous band.this is due
12464 * to race condition.but those channels are invalid to the new band and so
12465 * this function __ieee80211_get_channel will return NULL.Each time we
12466 * report scan result with this pointer null warning kernel trace is printed.
12467 * if the scan results contain large number of APs continuosly kernel
12468 * warning trace is printed and it will lead to apps watch dog bark.
12469 * So drop the bss and continue to next bss.
12470 */
12471 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012472 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12473 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012474 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012475 return NULL;
12476 }
12477
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012478 /* Based on .ini configuration, raw rssi can be reported for bss.
12479 * Raw rssi is typically used for estimating power.
12480 */
12481
12482 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12483 bss_desc->rssi;
12484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012485 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012486 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012487
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012488 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012489 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012490 (int)(rssi / 100),
12491 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012492
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012493 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12494 frame_len, rssi,
12495 GFP_KERNEL,
12496 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012497 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012498 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012499 return bss_status;
12500}
12501
12502/**
12503 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12504 * @pAdapter: Pointer to adapter
12505 * @pRoamInfo: Pointer to roam info
12506 *
12507 * This function is used to update the BSS data base of CFG8011
12508 *
12509 * Return: struct cfg80211_bss pointer
12510 */
12511struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12512 tCsrRoamInfo *pRoamInfo)
12513{
12514 tCsrRoamConnectedProfile roamProfile;
12515 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12516 struct cfg80211_bss *bss = NULL;
12517
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012518 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12519 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12520
12521 if (NULL != roamProfile.pBssDesc) {
12522 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12523 roamProfile.pBssDesc);
12524
12525 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012526 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012527
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012528 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012529 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012530 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012531 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012532 return bss;
12533}
12534/**
12535 * wlan_hdd_cfg80211_update_bss() - update bss
12536 * @wiphy: Pointer to wiphy
12537 * @pAdapter: Pointer to adapter
12538 * @scan_time: scan request timestamp
12539 *
12540 * Return: zero if success, non-zero otherwise
12541 */
12542int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12543 hdd_adapter_t *pAdapter,
12544 uint32_t scan_time)
12545{
12546 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12547 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012548 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012549 tScanResultHandle pResult;
12550 struct cfg80211_bss *bss_status = NULL;
12551 hdd_context_t *pHddCtx;
12552 int ret;
12553
12554 ENTER();
12555
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012556 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12557 hdd_err("invalid session id: %d", pAdapter->sessionId);
12558 return -EINVAL;
12559 }
12560
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012561 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012562 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12563 NO_SESSION, pAdapter->sessionId));
12564
12565 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12566 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012567 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012568 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012569
12570 /* start getting scan results and populate cgf80211 BSS database */
12571 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12572
12573 /* no scan results */
12574 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012575 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012576 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012577 }
12578
12579 pScanResult = sme_scan_result_get_first(hHal, pResult);
12580
12581 while (pScanResult) {
12582 /*
12583 * - cfg80211_inform_bss() is not updating ie field of bss
12584 * entry if entry already exists in bss data base of cfg80211
12585 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12586 * to update thebss entry instead of cfg80211_inform_bss,
12587 * But this call expects mgmt packet as input. As of now
12588 * there is no possibility to get the mgmt(probe response)
12589 * frame from PE, converting bss_desc to
12590 * ieee80211_mgmt(probe response) and passing to c
12591 * fg80211_inform_bss_frame.
12592 * - Update BSS only if beacon timestamp is later than
12593 * scan request timestamp.
12594 */
12595 if ((scan_time == 0) ||
12596 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012597 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012598 bss_status =
12599 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12600 &pScanResult->BssDescriptor);
12601
12602 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012603 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012604 } else {
12605 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012606 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607 bss_status);
12608 }
12609 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012610 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012611 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12612 }
12613 pScanResult = sme_scan_result_get_next(hHal, pResult);
12614 }
12615
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012616 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617 /*
12618 * For SAP mode, scan is invoked by hostapd during SAP start
12619 * if hostapd is restarted, we need to flush previous scan
12620 * result so that it will reflect environment change
12621 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012622 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012623#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12624 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12625#endif
12626 )
12627 sme_scan_flush_result(hHal);
12628
12629 EXIT();
12630 return 0;
12631}
12632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633/**
12634 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12635 * @pAdapter: Pointer to adapter
12636 * @pRoamInfo: Pointer to roam info
12637 * @index: Index
12638 * @preauth: Preauth flag
12639 *
12640 * This function is used to notify the supplicant of a new PMKSA candidate.
12641 *
12642 * Return: 0 for success, non-zero for failure
12643 */
12644int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12645 tCsrRoamInfo *pRoamInfo,
12646 int index, bool preauth)
12647{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012648 struct net_device *dev = pAdapter->dev;
12649 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12650
12651 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012652 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012653
12654 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012655 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012656 return -EINVAL;
12657 }
12658
12659 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012660 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012661 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12662 cfg80211_pmksa_candidate_notify(dev, index,
12663 pRoamInfo->bssid.bytes,
12664 preauth, GFP_KERNEL);
12665 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012666 return 0;
12667}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012668
12669#ifdef FEATURE_WLAN_LFR_METRICS
12670/**
12671 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12672 * @pAdapter: Pointer to adapter
12673 * @pRoamInfo: Pointer to roam info
12674 *
12675 * 802.11r/LFR metrics reporting function to report preauth initiation
12676 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012677 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012678 */
12679#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012680QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012681 tCsrRoamInfo *pRoamInfo)
12682{
12683 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12684 union iwreq_data wrqu;
12685
12686 ENTER();
12687
12688 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012689 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012690 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012691 }
12692
12693 /* create the event */
12694 memset(&wrqu, 0, sizeof(wrqu));
12695 memset(metrics_notification, 0, sizeof(metrics_notification));
12696
12697 wrqu.data.pointer = metrics_notification;
12698 wrqu.data.length = scnprintf(metrics_notification,
12699 sizeof(metrics_notification),
12700 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12701 MAC_ADDR_ARRAY(pRoamInfo->bssid));
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 * @preauth_status: Preauth status
12716 *
12717 * 802.11r/LFR metrics reporting function to report handover initiation
12718 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012719 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012720 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012721QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012722wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12723 tCsrRoamInfo *pRoamInfo,
12724 bool preauth_status)
12725{
12726 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12727 union iwreq_data wrqu;
12728
12729 ENTER();
12730
12731 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012732 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012733 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012734 }
12735
12736 /* create the event */
12737 memset(&wrqu, 0, sizeof(wrqu));
12738 memset(metrics_notification, 0, sizeof(metrics_notification));
12739
12740 scnprintf(metrics_notification, sizeof(metrics_notification),
12741 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12742 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12743
12744 if (1 == preauth_status)
12745 strlcat(metrics_notification, " true",
12746 sizeof(metrics_notification));
12747 else
12748 strlcat(metrics_notification, " false",
12749 sizeof(metrics_notification));
12750
12751 wrqu.data.pointer = metrics_notification;
12752 wrqu.data.length = strlen(metrics_notification);
12753
12754 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12755 metrics_notification);
12756
12757 EXIT();
12758
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012759 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760}
12761
12762/**
12763 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12764 * @pAdapter: Pointer to adapter
12765 * @pRoamInfo: Pointer to roam info
12766 *
12767 * 802.11r/LFR metrics reporting function to report handover initiation
12768 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012769 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012770 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012771QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012772 tCsrRoamInfo *pRoamInfo)
12773{
12774 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12775 union iwreq_data wrqu;
12776
12777 ENTER();
12778
12779 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012780 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012781 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782 }
12783
12784 /* create the event */
12785 memset(&wrqu, 0, sizeof(wrqu));
12786 memset(metrics_notification, 0, sizeof(metrics_notification));
12787
12788 wrqu.data.pointer = metrics_notification;
12789 wrqu.data.length = scnprintf(metrics_notification,
12790 sizeof(metrics_notification),
12791 "QCOM: LFR_PREAUTH_HANDOVER "
12792 MAC_ADDRESS_STR,
12793 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12794
12795 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12796 metrics_notification);
12797
12798 EXIT();
12799
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012800 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012801}
12802#endif
12803
12804/**
12805 * hdd_select_cbmode() - select channel bonding mode
12806 * @pAdapter: Pointer to adapter
12807 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012808 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012809 *
12810 * Return: none
12811 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012812void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080012813 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012814{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012815 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012816 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012817 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012818 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012819
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012820 /*
12821 * CDS api expects secondary channel for calculating
12822 * the channel params
12823 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012824 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012825 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012826 if (operationChannel >= 1 && operationChannel <= 5)
12827 sec_ch = operationChannel + 4;
12828 else if (operationChannel >= 6 && operationChannel <= 13)
12829 sec_ch = operationChannel - 4;
12830 }
12831
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012832 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012833 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
12834 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012835
12836 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012837 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012838 uint8_t iniDot11Mode =
12839 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12840
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012841 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012842 switch (iniDot11Mode) {
12843 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012844 case eHDD_DOT11_MODE_11ax:
12845 case eHDD_DOT11_MODE_11ax_ONLY:
12846 if (sme_is_feature_supported_by_fw(DOT11AX))
12847 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12848 else if (sme_is_feature_supported_by_fw(DOT11AC))
12849 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12850 else
12851 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12852 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012853 case eHDD_DOT11_MODE_11ac:
12854 case eHDD_DOT11_MODE_11ac_ONLY:
12855 if (sme_is_feature_supported_by_fw(DOT11AC))
12856 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12857 else
12858 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12859 break;
12860 case eHDD_DOT11_MODE_11n:
12861 case eHDD_DOT11_MODE_11n_ONLY:
12862 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12863 break;
12864 default:
12865 hdd_dot11_mode = iniDot11Mode;
12866 break;
12867 }
12868 ch_info->channel_width = ch_params->ch_width;
12869 ch_info->phy_mode =
12870 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012871 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012872 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012873 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012874 ch_info->channel_width, ch_info->phy_mode,
12875 ch_info->channel);
12876 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012877}
12878
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012879/**
12880 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12881 * @adapter: STA adapter
12882 * @roam_profile: STA roam profile
12883 *
12884 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12885 *
12886 * Return: false if sta-sap conc is not allowed, else return true
12887 */
12888static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12889 tCsrRoamProfile *roam_profile)
12890{
12891 hdd_context_t *hdd_ctx;
12892 hdd_adapter_t *ap_adapter;
12893 hdd_ap_ctx_t *hdd_ap_ctx;
12894 hdd_hostapd_state_t *hostapd_state;
12895 uint8_t channel = 0;
12896 QDF_STATUS status;
12897
12898 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12899 if (!hdd_ctx) {
12900 hdd_err("HDD context is NULL");
12901 return true;
12902 }
12903
12904 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12905 /* probably no sap running, no handling required */
12906 if (ap_adapter == NULL)
12907 return true;
12908
12909 /*
12910 * sap is not in started state, so it is fine to go ahead with sta.
12911 * if sap is currently doing CAC then don't allow sta to go further.
12912 */
12913 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12914 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12915 return true;
12916
12917 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12918 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12919 return false;
12920 }
12921
12922 /*
12923 * log and return error, if we allow STA to go through, we don't
12924 * know what is going to happen better stop sta connection
12925 */
12926 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12927 if (NULL == hdd_ap_ctx) {
12928 hdd_err("AP context not found");
12929 return false;
12930 }
12931
12932 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012933 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
12934 hdd_ap_ctx->operatingChannel)) {
12935 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012936 return true;
12937 }
12938 /*
12939 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012940 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012941 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012942 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012943 roam_profile, &channel);
12944
Nitesh Shah59774522016-09-16 15:14:21 +053012945 /*
12946 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12947 * channels for roaming case.
12948 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012949 if (WLAN_REG_IS_24GHZ_CH(channel)) {
12950 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012951 return true;
12952 }
12953
12954 /*
12955 * If channel is 0 or DFS then better to call pcl and find out the
12956 * best channel. If channel is non-dfs 5 GHz then better move SAP
12957 * to STA's channel to make scc, so we have room for 3port MCC
12958 * scenario.
12959 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012960 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012961 channel = policy_mgr_get_nondfs_preferred_channel(
12962 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012963
12964 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12965 qdf_event_reset(&hostapd_state->qdf_event);
12966 status = wlansap_set_channel_change_with_csa(
12967 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12968 hdd_ap_ctx->sapConfig.ch_width_orig);
12969
12970 if (QDF_STATUS_SUCCESS != status) {
12971 hdd_err("Set channel with CSA IE failed, can't allow STA");
12972 return false;
12973 }
12974
12975 /*
12976 * wait here for SAP to finish the channel switch. When channel
12977 * switch happens, SAP sends few beacons with CSA_IE. After
12978 * successfully Transmission of those beacons, it will move its
12979 * state from started to disconnected and move to new channel.
12980 * once it moves to new channel, sap again moves its state
12981 * machine from disconnected to started and set this event.
12982 * wait for 10 secs to finish this.
12983 */
12984 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12985 if (!QDF_IS_STATUS_SUCCESS(status)) {
12986 hdd_err("wait for qdf_event failed, STA not allowed!!");
12987 return false;
12988 }
12989
12990 return true;
12991}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012992
Abhishek Singhcfb44482017-03-10 12:42:37 +053012993#ifdef WLAN_FEATURE_11W
12994/**
12995 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12996 * @roam_profile: pointer to roam profile
12997 *
12998 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12999 * or pmf=2 is an explicit configuration in the supplicant
13000 * configuration, drop the connection request.
13001 *
13002 * Return: 0 if check result is valid, otherwise return error code
13003 */
13004static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13005{
13006 if (roam_profile->MFPEnabled &&
13007 !(roam_profile->MFPRequired ||
13008 roam_profile->MFPCapable)) {
13009 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13010 roam_profile->MFPEnabled,
13011 roam_profile->MFPRequired,
13012 roam_profile->MFPCapable);
13013 return -EINVAL;
13014 }
13015 return 0;
13016}
13017#else
13018static inline
13019int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13020{
13021 return 0;
13022}
13023#endif
13024
Krunal Soni31949422016-07-29 17:17:53 -070013025/**
13026 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013027 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013028 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013029 * @ssid_len: Length of ssid
13030 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013031 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013032 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013033 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013034 *
13035 * This function is used to start the association process
13036 *
13037 * Return: 0 for success, non-zero for failure
13038 */
Krunal Soni31949422016-07-29 17:17:53 -070013039static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013041 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013042 u8 operatingChannel,
13043 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013044{
13045 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013046 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013047 hdd_wext_state_t *pWextState;
13048 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013049 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013050 uint32_t roamId;
13051 tCsrRoamProfile *pRoamProfile;
13052 eCsrAuthType RSNAuthType;
13053 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013054 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013055
13056 ENTER();
13057
13058 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13059 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013060 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013061
13062 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013063 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013064 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013065
13066 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013067 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013068 status = -EINVAL;
13069 goto ret_status;
13070 }
13071
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013072 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013073 hdd_err("Connection refused: conn in progress");
13074 status = -EINVAL;
13075 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076 }
13077
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013078 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013079 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13080
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013081 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013082 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13083 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084
13085 if (pRoamProfile) {
13086 hdd_station_ctx_t *pHddStaCtx;
13087 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13088
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013089 /* Restart the opportunistic timer
13090 *
13091 * If hw_mode_change_in_progress is true, then wait
13092 * till firmware sends the callback for hw_mode change.
13093 *
13094 * Else set connect_in_progress as true and proceed.
13095 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013096 policy_mgr_restart_opportunistic_timer(
13097 pHddCtx->hdd_psoc, false);
13098 if (policy_mgr_is_hw_mode_change_in_progress(
13099 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013100 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013101 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013102 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013103 hdd_err("qdf wait for event failed!!");
13104 status = -EINVAL;
13105 goto ret_status;
13106 }
13107 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013108 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013109
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013110 if (HDD_WMM_USER_MODE_NO_QOS ==
13111 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13112 /*QoS not enabled in cfg file */
13113 pRoamProfile->uapsd_mask = 0;
13114 } else {
13115 /*QoS enabled, update uapsd mask from cfg file */
13116 pRoamProfile->uapsd_mask =
13117 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13118 }
13119
13120 pRoamProfile->SSIDs.numOfSSIDs = 1;
13121 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013122 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013123 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013124 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013125 ssid, ssid_len);
13126
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013127 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013128 /* cleanup bssid hint */
13129 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13130 QDF_MAC_ADDR_SIZE);
13131 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13132 QDF_MAC_ADDR_SIZE);
13133
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013134 if (bssid) {
13135 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013136 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013137 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013138 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013139 /*
13140 * Save BSSID in seperate variable as
13141 * pRoamProfile's BSSID is getting zeroed out in the
13142 * association process. In case of join failure
13143 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013144 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013145 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013146 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013147 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013148 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013149 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13150 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013151 /*
13152 * Save BSSID in a separate variable as
13153 * pRoamProfile's BSSID is getting zeroed out in the
13154 * association process. In case of join failure
13155 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013156 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013157 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013158 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013159 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013160 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013161 }
13162
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013163 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013164 pRoamProfile->SSIDs.SSIDList->SSID.length,
13165 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13166 operatingChannel);
13167
13168 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13169 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013170 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013171 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13172 }
13173#ifdef FEATURE_WLAN_WAPI
13174 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013175 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013176 switch (pAdapter->wapi_info.wapiAuthMode) {
13177 case WAPI_AUTH_MODE_PSK:
13178 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013179 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013180 pAdapter->wapi_info.wapiAuthMode);
13181 pRoamProfile->AuthType.authType[0] =
13182 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13183 break;
13184 }
13185 case WAPI_AUTH_MODE_CERT:
13186 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013187 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013188 pAdapter->wapi_info.wapiAuthMode);
13189 pRoamProfile->AuthType.authType[0] =
13190 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13191 break;
13192 }
13193 } /* End of switch */
13194 if (pAdapter->wapi_info.wapiAuthMode ==
13195 WAPI_AUTH_MODE_PSK
13196 || pAdapter->wapi_info.wapiAuthMode ==
13197 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013198 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013199 pRoamProfile->AuthType.numEntries = 1;
13200 pRoamProfile->EncryptionType.numEntries = 1;
13201 pRoamProfile->EncryptionType.encryptionType[0] =
13202 eCSR_ENCRYPT_TYPE_WPI;
13203 pRoamProfile->mcEncryptionType.numEntries = 1;
13204 pRoamProfile->mcEncryptionType.
13205 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13206 }
13207 }
Krunal Soni31949422016-07-29 17:17:53 -070013208#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013209 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013210 pRoamProfile->csrPersona = pAdapter->device_mode;
13211
13212 if (operatingChannel) {
13213 pRoamProfile->ChannelInfo.ChannelList =
13214 &operatingChannel;
13215 pRoamProfile->ChannelInfo.numOfChannels = 1;
13216 } else {
13217 pRoamProfile->ChannelInfo.ChannelList = NULL;
13218 pRoamProfile->ChannelInfo.numOfChannels = 0;
13219 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013220 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013221 && operatingChannel) {
13222 /*
13223 * Need to post the IBSS power save parameters
13224 * to WMA. WMA will configure this parameters
13225 * to firmware if power save is enabled by the
13226 * firmware.
13227 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013228 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013229
Abhishek Singh471652b2017-04-14 12:28:32 +053013230 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013231 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013232 status = -EINVAL;
13233 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013234 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013235 pRoamProfile->ch_params.ch_width =
13236 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013237 /*
13238 * In IBSS mode while operating in 2.4 GHz,
13239 * the device supports only 20 MHz.
13240 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013241 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013242 pRoamProfile->ch_params.ch_width =
13243 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013244 hdd_select_cbmode(pAdapter, operatingChannel,
13245 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013246 }
13247
Abhishek Singhcfb44482017-03-10 12:42:37 +053013248 if (wlan_hdd_cfg80211_check_pmf_valid(
13249 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013250 status = -EINVAL;
13251 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013252 }
13253
Krunal Soni31949422016-07-29 17:17:53 -070013254 /*
13255 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013256 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013257 * enhancements, the supplicant is not issuing the scan command
13258 * now. So the unicast frames which are sent from the host are
13259 * not having the additional IEs. If it is P2P CLIENT and there
13260 * is no additional IE present in roamProfile, then use the
13261 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013262 */
13263
Krunal Sonib4326f22016-03-10 13:05:51 -080013264 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013265 (!pRoamProfile->pAddIEScan)) {
13266 pRoamProfile->pAddIEScan =
13267 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13268 pRoamProfile->nAddIEScanLength =
13269 pAdapter->scan_info.scanAddIE.length;
13270 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013271
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013272 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13273 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013274 pRoamProfile))) {
13275 hdd_err("sap-sta conc will fail, can't allow sta");
13276 hdd_conn_set_connection_state(pAdapter,
13277 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013278 status = -ENOMEM;
13279 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013280 }
13281
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013282 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013283 if (!sme_config) {
13284 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013285 hdd_conn_set_connection_state(pAdapter,
13286 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013287 status = -ENOMEM;
13288 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013289 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013290 sme_get_config_param(pHddCtx->hHal, sme_config);
13291 /* These values are not sessionized. So, any change in these SME
13292 * configs on an older or parallel interface will affect the
13293 * cb mode. So, restoring the default INI params before starting
13294 * interfaces such as sta, cli etc.,
13295 */
13296 sme_config->csrConfig.channelBondingMode5GHz =
13297 pHddCtx->config->nChannelBondingMode5GHz;
13298 sme_config->csrConfig.channelBondingMode24GHz =
13299 pHddCtx->config->nChannelBondingMode24GHz;
13300 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013301 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013302 /*
13303 * Change conn_state to connecting before sme_roam_connect(),
13304 * because sme_roam_connect() has a direct path to call
13305 * hdd_sme_roam_callback(), which will change the conn_state
13306 * If direct path, conn_state will be accordingly changed to
13307 * NotConnected or Associated by either
13308 * hdd_association_completion_handler() or
13309 * hdd_dis_connect_handler() in sme_RoamCallback()if
13310 * sme_RomConnect is to be queued,
13311 * Connecting state will remain until it is completed.
13312 *
13313 * If connection state is not changed, connection state will
13314 * remain in eConnectionState_NotConnected state.
13315 * In hdd_association_completion_handler, "hddDisconInProgress"
13316 * is set to true if conn state is
13317 * eConnectionState_NotConnected.
13318 * If "hddDisconInProgress" is set to true then cfg80211 layer
13319 * is not informed of connect result indication which
13320 * is an issue.
13321 */
13322 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013323 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013324 hdd_conn_set_connection_state(pAdapter,
13325 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013326
Komal Seelama89be8d2016-09-29 11:09:26 +053013327 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13328 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013329 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013330 pAdapter->sessionId, pRoamProfile,
13331 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013332 if (QDF_IS_STATUS_ERROR(qdf_status))
13333 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013334
Rajeev Kumard31e1542017-01-13 14:37:42 -080013335 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013336 (QDF_STA_MODE == pAdapter->device_mode ||
13337 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013338 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013339 "qdf_status %d. -> NotConnected",
13340 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013341 /* change back to NotAssociated */
13342 hdd_conn_set_connection_state(pAdapter,
13343 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013344 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13345 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346 }
13347
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013348 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013349 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013351 pRoamProfile->ChannelInfo.ChannelList = NULL;
13352 pRoamProfile->ChannelInfo.numOfChannels = 0;
13353
Nitesh Shah044fd672016-10-13 18:53:25 +053013354 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013355 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13356 && !policy_mgr_is_hw_dbs_2x2_capable(
13357 pHddCtx->hdd_psoc)) {
13358 policy_mgr_get_channel_from_scan_result(
13359 pHddCtx->hdd_psoc,
13360 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013361 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013362 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013363 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13364 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013365 }
13366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013367 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013368 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013369 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013370 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013371 goto ret_status;
13372
13373conn_failure:
13374 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013375 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013376
13377ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013378 EXIT();
13379 return status;
13380}
13381
13382/**
13383 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13384 * @pAdapter: Pointer to adapter
13385 * @auth_type: Auth type
13386 *
13387 * This function is used to set the authentication type (OPEN/SHARED).
13388 *
13389 * Return: 0 for success, non-zero for failure
13390 */
13391static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13392 enum nl80211_auth_type auth_type)
13393{
13394 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13395 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13396
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013397 /*set authentication type */
13398 switch (auth_type) {
13399 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013400 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013401 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13402 break;
13403
13404 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013405 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013406 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013407 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13408 break;
13409
13410 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013411 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013412 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13413 break;
13414#ifdef FEATURE_WLAN_ESE
13415 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013416 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013417 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13418 break;
13419#endif
13420
13421 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013422 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013423 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13424 return -EINVAL;
13425 }
13426
13427 pWextState->roamProfile.AuthType.authType[0] =
13428 pHddStaCtx->conn_info.authType;
13429 return 0;
13430}
13431
13432/**
13433 * wlan_hdd_set_akm_suite() - set key management type
13434 * @pAdapter: Pointer to adapter
13435 * @key_mgmt: Key management type
13436 *
13437 * This function is used to set the key mgmt type(PSK/8021x).
13438 *
13439 * Return: 0 for success, non-zero for failure
13440 */
13441static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13442{
13443 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13444
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013445#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013446#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013447#endif
13448#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013449#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013450#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013451 /*set key mgmt type */
13452 switch (key_mgmt) {
13453 case WLAN_AKM_SUITE_PSK:
13454 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013456 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013457 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13458 break;
13459
13460 case WLAN_AKM_SUITE_8021X_SHA256:
13461 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013462 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013463 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013464 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13465 break;
13466#ifdef FEATURE_WLAN_ESE
13467#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13468#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13469 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013470 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013471 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13472 break;
13473#endif
13474#ifndef WLAN_AKM_SUITE_OSEN
13475#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13476#endif
13477 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013478 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013479 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13480 break;
13481
13482 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013483 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013484 return -EINVAL;
13485
13486 }
13487 return 0;
13488}
13489
13490/**
13491 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13492 * @pAdapter: Pointer to adapter
13493 * @cipher: Cipher type
13494 * @ucast: Unicast flag
13495 *
13496 * This function is used to set the encryption type
13497 * (NONE/WEP40/WEP104/TKIP/CCMP).
13498 *
13499 * Return: 0 for success, non-zero for failure
13500 */
13501static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13502 u32 cipher, bool ucast)
13503{
13504 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13505 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13506 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013508 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013509 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013510 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13511 } else {
13512
13513 /*set encryption method */
13514 switch (cipher) {
13515 case IW_AUTH_CIPHER_NONE:
13516 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13517 break;
13518
13519 case WLAN_CIPHER_SUITE_WEP40:
13520 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13521 break;
13522
13523 case WLAN_CIPHER_SUITE_WEP104:
13524 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13525 break;
13526
13527 case WLAN_CIPHER_SUITE_TKIP:
13528 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13529 break;
13530
13531 case WLAN_CIPHER_SUITE_CCMP:
13532 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13533 break;
13534#ifdef FEATURE_WLAN_WAPI
13535 case WLAN_CIPHER_SUITE_SMS4:
13536 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13537 break;
13538#endif
13539
13540#ifdef FEATURE_WLAN_ESE
13541 case WLAN_CIPHER_SUITE_KRK:
13542 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13543 break;
13544#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13545 case WLAN_CIPHER_SUITE_BTK:
13546 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13547 break;
13548#endif
13549#endif
13550 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013551 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013552 return -EOPNOTSUPP;
13553 }
13554 }
13555
13556 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013557 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013558 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13559 pWextState->roamProfile.EncryptionType.numEntries = 1;
13560 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13561 encryptionType;
13562 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013563 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013564 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13565 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13566 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13567 encryptionType;
13568 }
13569
13570 return 0;
13571}
13572
13573/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013574 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13575 * @wext_state: Pointer to wext state
13576 * @gen_ie: Pointer to IE data
13577 * @len: length of IE data
13578 *
13579 * Return: 0 for success, non-zero for failure
13580 */
13581static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13582 const uint8_t *gen_ie, uint16_t len)
13583{
13584 uint16_t cur_add_ie_len =
13585 wext_state->assocAddIE.length;
13586
13587 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13588 (wext_state->assocAddIE.length + len)) {
13589 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13590 QDF_ASSERT(0);
13591 return -ENOMEM;
13592 }
13593 memcpy(wext_state->assocAddIE.addIEdata +
13594 cur_add_ie_len, gen_ie, len);
13595 wext_state->assocAddIE.length += len;
13596
13597 wext_state->roamProfile.pAddIEAssoc =
13598 wext_state->assocAddIE.addIEdata;
13599 wext_state->roamProfile.nAddIEAssocLength =
13600 wext_state->assocAddIE.length;
13601 return 0;
13602}
13603
13604/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013605 * wlan_hdd_cfg80211_set_ie() - set IEs
13606 * @pAdapter: Pointer to adapter
13607 * @ie: Pointer ot ie
13608 * @ie: IE length
13609 *
13610 * Return: 0 for success, non-zero for failure
13611 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013612static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013613 size_t ie_len)
13614{
13615 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13616 const uint8_t *genie = ie;
13617 uint16_t remLen = ie_len;
13618#ifdef FEATURE_WLAN_WAPI
13619 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13620 u16 *tmp;
13621 uint16_t akmsuiteCount;
13622 int *akmlist;
13623#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013624 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013625
13626 /* clear previous assocAddIE */
13627 pWextState->assocAddIE.length = 0;
13628 pWextState->roamProfile.bWPSAssociation = false;
13629 pWextState->roamProfile.bOSENAssociation = false;
13630
13631 while (remLen >= 2) {
13632 uint16_t eLen = 0;
13633 uint8_t elementId;
13634 elementId = *genie++;
13635 eLen = *genie++;
13636 remLen -= 2;
13637
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013638 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639
13640 switch (elementId) {
13641 case DOT11F_EID_WPA:
13642 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 -070013643 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013644 return -EINVAL;
13645 } else if (0 ==
13646 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13647 uint16_t curAddIELen =
13648 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013649 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013650
13651 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13652 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013653 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013654 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013655 return -ENOMEM;
13656 }
13657 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13658 memcpy(pWextState->assocAddIE.addIEdata +
13659 curAddIELen, genie - 2, eLen + 2);
13660 pWextState->assocAddIE.length += eLen + 2;
13661
13662 pWextState->roamProfile.bWPSAssociation = true;
13663 pWextState->roamProfile.pAddIEAssoc =
13664 pWextState->assocAddIE.addIEdata;
13665 pWextState->roamProfile.nAddIEAssocLength =
13666 pWextState->assocAddIE.length;
13667 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013668 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013669 memset(pWextState->WPARSNIE, 0,
13670 MAX_WPA_RSN_IE_LEN);
13671 memcpy(pWextState->WPARSNIE, genie - 2,
13672 (eLen + 2));
13673 pWextState->roamProfile.pWPAReqIE =
13674 pWextState->WPARSNIE;
13675 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13676 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13677 P2P_OUI_TYPE_SIZE))) {
13678 uint16_t curAddIELen =
13679 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013680 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013681
13682 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13683 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013684 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013685 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013686 return -ENOMEM;
13687 }
13688 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13689 memcpy(pWextState->assocAddIE.addIEdata +
13690 curAddIELen, genie - 2, eLen + 2);
13691 pWextState->assocAddIE.length += eLen + 2;
13692
13693 pWextState->roamProfile.pAddIEAssoc =
13694 pWextState->assocAddIE.addIEdata;
13695 pWextState->roamProfile.nAddIEAssocLength =
13696 pWextState->assocAddIE.length;
13697 }
13698#ifdef WLAN_FEATURE_WFD
13699 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13700 WFD_OUI_TYPE_SIZE)) &&
13701 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013702 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013703 pAdapter->device_mode)) {
13704 uint16_t curAddIELen =
13705 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013706 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013707
13708 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13709 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013710 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013711 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013712 return -ENOMEM;
13713 }
13714 /* WFD IE is saved to Additional IE ; it should
13715 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013716 * WFD IE
13717 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013718 memcpy(pWextState->assocAddIE.addIEdata +
13719 curAddIELen, genie - 2, eLen + 2);
13720 pWextState->assocAddIE.length += eLen + 2;
13721
13722 pWextState->roamProfile.pAddIEAssoc =
13723 pWextState->assocAddIE.addIEdata;
13724 pWextState->roamProfile.nAddIEAssocLength =
13725 pWextState->assocAddIE.length;
13726 }
13727#endif
13728 /* Appending HS 2.0 Indication Element in Assiciation Request */
13729 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13730 HS20_OUI_TYPE_SIZE))) {
13731 uint16_t curAddIELen =
13732 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013733 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013734
13735 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13736 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013737 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013738 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013739 return -ENOMEM;
13740 }
13741 memcpy(pWextState->assocAddIE.addIEdata +
13742 curAddIELen, genie - 2, eLen + 2);
13743 pWextState->assocAddIE.length += eLen + 2;
13744
13745 pWextState->roamProfile.pAddIEAssoc =
13746 pWextState->assocAddIE.addIEdata;
13747 pWextState->roamProfile.nAddIEAssocLength =
13748 pWextState->assocAddIE.length;
13749 }
13750 /* Appending OSEN Information Element in Assiciation Request */
13751 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13752 OSEN_OUI_TYPE_SIZE))) {
13753 uint16_t curAddIELen =
13754 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013755 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013756
13757 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13758 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013759 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013760 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013761 return -ENOMEM;
13762 }
13763 memcpy(pWextState->assocAddIE.addIEdata +
13764 curAddIELen, genie - 2, eLen + 2);
13765 pWextState->assocAddIE.length += eLen + 2;
13766
13767 pWextState->roamProfile.bOSENAssociation = true;
13768 pWextState->roamProfile.pAddIEAssoc =
13769 pWextState->assocAddIE.addIEdata;
13770 pWextState->roamProfile.nAddIEAssocLength =
13771 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013772 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13773 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013774 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013775 status = wlan_hdd_add_assoc_ie(pWextState,
13776 genie - 2, eLen + 2);
13777 if (status)
13778 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013779 } else {
13780 uint16_t add_ie_len =
13781 pWextState->assocAddIE.length;
13782
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013783 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013784
13785 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13786 (pWextState->assocAddIE.length + eLen)) {
13787 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013788 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013789 return -ENOMEM;
13790 }
13791
13792 memcpy(pWextState->assocAddIE.addIEdata +
13793 add_ie_len, genie - 2, eLen + 2);
13794 pWextState->assocAddIE.length += eLen + 2;
13795
13796 pWextState->roamProfile.pAddIEAssoc =
13797 pWextState->assocAddIE.addIEdata;
13798 pWextState->roamProfile.nAddIEAssocLength =
13799 pWextState->assocAddIE.length;
13800 }
13801 break;
13802 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013803 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013804 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13805 memcpy(pWextState->WPARSNIE, genie - 2,
13806 (eLen + 2));
13807 pWextState->roamProfile.pRSNReqIE =
13808 pWextState->WPARSNIE;
13809 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13810 break;
13811 /*
13812 * Appending Extended Capabilities with Interworking bit set
13813 * in Assoc Req.
13814 *
13815 * In assoc req this EXT Cap will only be taken into account if
13816 * interworkingService bit is set to 1. Currently
13817 * driver is only interested in interworkingService capability
13818 * from supplicant. If in future any other EXT Cap info is
13819 * required from supplicat, it needs to be handled while
13820 * sending Assoc Req in LIM.
13821 */
13822 case DOT11F_EID_EXTCAP:
13823 {
13824 uint16_t curAddIELen =
13825 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013826 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013827
13828 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13829 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013830 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013831 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013832 return -ENOMEM;
13833 }
13834 memcpy(pWextState->assocAddIE.addIEdata +
13835 curAddIELen, genie - 2, eLen + 2);
13836 pWextState->assocAddIE.length += eLen + 2;
13837
13838 pWextState->roamProfile.pAddIEAssoc =
13839 pWextState->assocAddIE.addIEdata;
13840 pWextState->roamProfile.nAddIEAssocLength =
13841 pWextState->assocAddIE.length;
13842 break;
13843 }
13844#ifdef FEATURE_WLAN_WAPI
13845 case WLAN_EID_WAPI:
13846 /* Setting WAPI Mode to ON=1 */
13847 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013848 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013849 tmp = (u16 *) ie;
13850 tmp = tmp + 2; /* Skip element Id and Len, Version */
13851 akmsuiteCount = WPA_GET_LE16(tmp);
13852 tmp = tmp + 1;
13853 akmlist = (int *)(tmp);
13854 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13855 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13856 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013857 hdd_err("Invalid akmSuite count: %u",
13858 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013859 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013860 return -EINVAL;
13861 }
13862
13863 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013864 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013865 pAdapter->wapi_info.wapiAuthMode =
13866 WAPI_AUTH_MODE_PSK;
13867 }
13868 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013869 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013870 pAdapter->wapi_info.wapiAuthMode =
13871 WAPI_AUTH_MODE_CERT;
13872 }
13873 break;
13874#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013875 case DOT11F_EID_SUPPOPERATINGCLASSES:
13876 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013877 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013878 status = wlan_hdd_add_assoc_ie(pWextState,
13879 genie - 2, eLen + 2);
13880 if (status)
13881 return status;
13882 break;
13883 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013884 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013885 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013886 /* when Unknown IE is received we break
13887 * and continue to the next IE in the buffer
13888 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013889 break;
13890 }
13891 genie += eLen;
13892 remLen -= eLen;
13893 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013894 return 0;
13895}
13896
13897/**
13898 * hdd_is_wpaie_present() - check for WPA ie
13899 * @ie: Pointer to ie
13900 * @ie_len: Ie length
13901 *
13902 * Parse the received IE to find the WPA IE
13903 *
13904 * Return: true if wpa ie is found else false
13905 */
13906static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13907{
13908 uint8_t eLen = 0;
13909 uint16_t remLen = ie_len;
13910 uint8_t elementId = 0;
13911
13912 while (remLen >= 2) {
13913 elementId = *ie++;
13914 eLen = *ie++;
13915 remLen -= 2;
13916 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013917 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013918 return false;
13919 }
13920 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13921 /* OUI - 0x00 0X50 0XF2
13922 * WPA Information Element - 0x01
13923 * WPA version - 0x01
13924 */
13925 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13926 return true;
13927 }
13928 ie += eLen;
13929 remLen -= eLen;
13930 }
13931 return false;
13932}
13933
13934/**
13935 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13936 * @pAdapter: Pointer to adapter
13937 * @req: Pointer to security parameters
13938 *
13939 * Return: 0 for success, non-zero for failure
13940 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013941static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13942 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013943{
13944 int status = 0;
13945 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13946 ENTER();
13947
13948 /*set wpa version */
13949 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13950
13951 if (req->crypto.wpa_versions) {
13952 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13953 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13954 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13955 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13956 }
13957 }
13958
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013959 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013960
13961 /*set authentication type */
13962 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13963
13964 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013965 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013966 return status;
13967 }
13968
13969 /*set key mgmt type */
13970 if (req->crypto.n_akm_suites) {
13971 status =
13972 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13973 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013974 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013975 return status;
13976 }
13977 }
13978
13979 /*set pairwise cipher type */
13980 if (req->crypto.n_ciphers_pairwise) {
13981 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13982 req->crypto.
13983 ciphers_pairwise[0],
13984 true);
13985 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013986 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013987 return status;
13988 }
13989 } else {
13990 /*Reset previous cipher suite to none */
13991 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13992 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013993 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013994 return status;
13995 }
13996 }
13997
13998 /*set group cipher type */
13999 status =
14000 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14001 false);
14002
14003 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014004 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014005 return status;
14006 }
14007#ifdef WLAN_FEATURE_11W
14008 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14009#endif
14010
14011 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14012 if (req->ie_len) {
14013 status =
14014 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14015 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014016 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014017 return status;
14018 }
14019 }
14020
14021 /*incase of WEP set default key information */
14022 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014023 u8 key_len = req->key_len;
14024 u8 key_idx = req->key_idx;
14025
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014026 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14027 || (WLAN_CIPHER_SUITE_WEP104 ==
14028 req->crypto.ciphers_pairwise[0])
14029 ) {
14030 if (IW_AUTH_KEY_MGMT_802_1X
14031 ==
14032 (pWextState->
14033 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014034 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014035 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014036 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014037
Jeff Johnson68755312017-02-10 11:46:55 -080014038 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14039 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014040 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014041 key_idx, key_len);
14042 qdf_mem_copy(&pWextState->roamProfile.
14043 Keys.
14044 KeyMaterial[key_idx][0],
14045 req->key, key_len);
14046 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014047 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014048 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014049 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014050 }
14051 }
14052 }
14053
14054 return status;
14055}
14056
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014057int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014058{
14059 unsigned long rc;
14060 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014061 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014062 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014063
14064 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014065 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14066 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014067 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014068 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14069 }
14070 /*
14071 * If firmware has already started roaming process, driver
14072 * needs to defer the processing of this disconnect request.
14073 *
14074 */
14075 if (hdd_is_roaming_in_progress(pAdapter)) {
14076 /*
14077 * Defer the disconnect action until firmware roaming
14078 * result is received. If STA is in connected state after
14079 * that, send the disconnect command to CSR, otherwise
14080 * CSR would have already sent disconnect event to upper
14081 * layer.
14082 */
14083
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014084 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014085 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14086 pAdapter->cfg80211_disconnect_reason =
14087 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14088 return 0;
14089 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014090
Jeff Johnson9edf9572016-10-03 15:24:49 -070014091 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014092 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14093 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14094 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014095 hdd_conn_set_connection_state(pAdapter,
14096 eConnectionState_Disconnecting);
14097 /* Issue disconnect to CSR */
14098 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014099
14100 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14101 pAdapter->sessionId,
14102 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14103 /*
14104 * Wait here instead of returning directly, this will block the
14105 * next connect command and allow processing of the scan for
14106 * ssid and the previous connect command in CSR. Else we might
14107 * hit some race conditions leading to SME and HDD out of sync.
14108 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014109 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014110 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014111 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014112 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014113 (int)status);
14114 pHddStaCtx->staDebugState = status;
14115 result = -EINVAL;
14116 goto disconnected;
14117 }
14118
14119 rc = wait_for_completion_timeout(
14120 &pAdapter->disconnect_comp_var,
14121 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014122 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014123 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014124 pAdapter->sessionId, pHddStaCtx->staDebugState);
14125 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014126 }
14127 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014128 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014129 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014130 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014131 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014132 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014133 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014134 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014135 }
14136 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014137disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014138 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14139 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014140}
14141
14142/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014143 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14144 * @adapter: Pointer to the HDD adapter
14145 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014146 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014147 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014148 * This function will start reassociation if prev_bssid is set and bssid/
14149 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014150 *
Naveen Rawat07332902016-07-27 09:13:17 -070014151 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014152 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014153#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14154 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014155static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14156 struct cfg80211_connect_params *req,
14157 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014158{
Naveen Rawat07332902016-07-27 09:13:17 -070014159 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014160 const uint8_t *bssid = NULL;
14161 uint16_t channel = 0;
14162
14163 if (req->bssid)
14164 bssid = req->bssid;
14165 else if (req->bssid_hint)
14166 bssid = req->bssid_hint;
14167
14168 if (req->channel)
14169 channel = req->channel->hw_value;
14170 else if (req->channel_hint)
14171 channel = req->channel_hint->hw_value;
14172
14173 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014174 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014175 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014176 channel, MAC_ADDR_ARRAY(bssid));
14177 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014178 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014179 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014180 }
Naveen Rawat07332902016-07-27 09:13:17 -070014181 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014182}
14183#else
Naveen Rawat07332902016-07-27 09:13:17 -070014184static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14185 struct cfg80211_connect_params *req,
14186 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014187{
Naveen Rawat07332902016-07-27 09:13:17 -070014188 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014189}
14190#endif
14191
14192/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014193 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14194 * @wiphy: Pointer to wiphy
14195 * @dev: Pointer to network device
14196 * @req: Pointer to cfg80211 connect request
14197 *
14198 * This function is used to start the association process
14199 *
14200 * Return: 0 for success, non-zero for failure
14201 */
14202static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14203 struct net_device *ndev,
14204 struct cfg80211_connect_params *req)
14205{
14206 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014207 u16 channel;
14208#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14209 const u8 *bssid_hint = req->bssid_hint;
14210#else
14211 const u8 *bssid_hint = NULL;
14212#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014213 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14214 hdd_context_t *pHddCtx;
14215
14216 ENTER();
14217
Anurag Chouhan6d760662016-02-20 16:05:43 +053014218 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014219 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014220 return -EINVAL;
14221 }
14222
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014223 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14224 hdd_err("invalid session id: %d", pAdapter->sessionId);
14225 return -EINVAL;
14226 }
14227
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014228 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014229 TRACE_CODE_HDD_CFG80211_CONNECT,
14230 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014231 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232 hdd_device_mode_to_string(pAdapter->device_mode),
14233 pAdapter->device_mode);
14234
Krunal Sonib4326f22016-03-10 13:05:51 -080014235 if (pAdapter->device_mode != QDF_STA_MODE &&
14236 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014237 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014238 hdd_device_mode_to_string(pAdapter->device_mode),
14239 pAdapter->device_mode);
14240 return -EINVAL;
14241 }
14242
14243 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14244 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014245 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014246 return -EINVAL;
14247 }
14248
14249 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014250 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014251 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014252
Naveen Rawat07332902016-07-27 09:13:17 -070014253 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014254 return status;
14255
Agrawal Ashishf156e942016-08-04 14:54:47 +053014256 /* Try disconnecting if already in connected state */
14257 status = wlan_hdd_try_disconnect(pAdapter);
14258 if (0 > status) {
14259 hdd_err("Failed to disconnect the existing connection");
14260 return -EALREADY;
14261 }
14262
14263 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014264 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014265 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14266 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014267 pAdapter->device_mode),
14268 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014269 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014270 return -ECONNREFUSED;
14271 }
14272 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014273 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14274 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014275 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014276 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014277 return -ECONNREFUSED;
14278 }
14279 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014280
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014281 /*initialise security parameters */
14282 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14283
14284 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014285 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014286 return status;
14287 }
14288
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014289 if (req->channel)
14290 channel = req->channel->hw_value;
14291 else
14292 channel = 0;
14293 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14294 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014295 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014296 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014297 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014298 return status;
14299 }
14300 EXIT();
14301 return status;
14302}
14303
14304/**
14305 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14306 * @wiphy: Pointer to wiphy
14307 * @dev: Pointer to network device
14308 * @req: Pointer to cfg80211 connect request
14309 *
14310 * Return: 0 for success, non-zero for failure
14311 */
14312static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14313 struct net_device *ndev,
14314 struct cfg80211_connect_params *req)
14315{
14316 int ret;
14317 cds_ssr_protect(__func__);
14318 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14319 cds_ssr_unprotect(__func__);
14320
14321 return ret;
14322}
14323
14324/**
14325 * wlan_hdd_disconnect() - hdd disconnect api
14326 * @pAdapter: Pointer to adapter
14327 * @reason: Disconnect reason code
14328 *
14329 * This function is used to issue a disconnect request to SME
14330 *
14331 * Return: 0 for success, non-zero for failure
14332 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014333static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014334{
14335 int status, result = 0;
14336 unsigned long rc;
14337 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14338 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014339 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014340 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014341
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014342 ENTER();
14343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 status = wlan_hdd_validate_context(pHddCtx);
14345
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014346 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014348 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014349 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014350 status = sme_stop_roaming(hal, pAdapter->sessionId,
14351 eCsrHddIssued);
14352 }
14353 /*
14354 * If firmware has already started roaming process, driver
14355 * needs to defer the processing of this disconnect request.
14356 */
14357 if (hdd_is_roaming_in_progress(pAdapter)) {
14358 /*
14359 * Defer the disconnect action until firmware roaming
14360 * result is received. If STA is in connected state after
14361 * that, send the disconnect command to CSR, otherwise
14362 * CSR would have already sent disconnect event to upper
14363 * layer.
14364 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014365 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014366 pAdapter->defer_disconnect =
14367 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14368 pAdapter->cfg80211_disconnect_reason = reason;
14369 return 0;
14370 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014371
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014372 prev_conn_state = pHddStaCtx->conn_info.connState;
14373
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014374 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014375 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014376 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014377 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014378 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014379 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14380 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14381
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014382 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014383
14384 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14385 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014386 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14387 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014388 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014389 result = 0;
14390 goto disconnected;
14391 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14392 /*
14393 * Wait here instead of returning directly, this will block the
14394 * next connect command and allow processing of the scan for
14395 * ssid and the previous connect command in CSR. Else we might
14396 * hit some race conditions leading to SME and HDD out of sync.
14397 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014398 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014399 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014400 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014401 pHddStaCtx->staDebugState = status;
14402 result = -EINVAL;
14403 goto disconnected;
14404 }
14405 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14406 msecs_to_jiffies
14407 (WLAN_WAIT_TIME_DISCONNECT));
14408
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014409 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014410 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014411 result = -ETIMEDOUT;
14412 }
14413disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014414 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14415#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14416 /* Sending disconnect event to userspace for kernel version < 3.11
14417 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14418 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014419 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014420 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14421 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014422#endif
14423
14424 return result;
14425}
14426
14427/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014428 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14429 * @reason: ieee80211 reason code.
14430 *
14431 * This utility function helps log string conversion of reason code.
14432 *
14433 * Return: string conversion of reason code, if match found;
14434 * "Unknown" otherwise.
14435 */
14436static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14437{
14438 switch (reason) {
14439 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14440 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14441 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14442 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14443 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14444 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14445 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14446 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14447 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14448 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14449 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14450 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14451 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14452 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14453 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14454 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14455 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14456 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14457 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14458 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14459 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14460 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14461 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14462 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14463 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14464 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14465 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14466 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14467 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14468 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14469 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14470 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14471 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14472 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14473 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14474 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14475 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14476 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14477 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14478 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14479 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14480 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14481 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14482 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14483 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14484 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14485 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14486 default:
14487 return "Unknown";
14488 }
14489}
14490
14491/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014492 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14493 * @wiphy: Pointer to wiphy
14494 * @dev: Pointer to network device
14495 * @reason: Disconnect reason code
14496 *
14497 * This function is used to issue a disconnect request to SME
14498 *
14499 * Return: 0 for success, non-zero for failure
14500 */
14501static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14502 struct net_device *dev, u16 reason)
14503{
14504 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14505 int status;
14506 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14507 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14508#ifdef FEATURE_WLAN_TDLS
14509 uint8_t staIdx;
14510#endif
14511
14512 ENTER();
14513
Anurag Chouhan6d760662016-02-20 16:05:43 +053014514 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014515 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014516 return -EINVAL;
14517 }
14518
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014519 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014520 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014521 return -EINVAL;
14522 }
14523
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014524 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014525 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14526 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014527 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014528 hdd_device_mode_to_string(pAdapter->device_mode),
14529 pAdapter->device_mode, reason);
14530
14531 status = wlan_hdd_validate_context(pHddCtx);
14532
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014533 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014534 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014535
14536 /* Issue disconnect request to SME, if station is in connected state */
14537 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14538 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14539 eCsrRoamDisconnectReason reasonCode =
14540 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14541 hdd_scaninfo_t *pScanInfo;
14542
14543 switch (reason) {
14544 case WLAN_REASON_MIC_FAILURE:
14545 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14546 break;
14547
14548 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14549 case WLAN_REASON_DISASSOC_AP_BUSY:
14550 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14551 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14552 break;
14553
14554 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14555 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14556 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14557 break;
14558
14559 case WLAN_REASON_DEAUTH_LEAVING:
14560 reasonCode =
14561 pHddCtx->config->
14562 gEnableDeauthToDisassocMap ?
14563 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14564 eCSR_DISCONNECT_REASON_DEAUTH;
14565 break;
14566 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14567 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14568 break;
14569 default:
14570 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14571 break;
14572 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014573 pScanInfo = &pAdapter->scan_info;
14574 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014575 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014576 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014577 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014578 eCSR_SCAN_ABORT_DEFAULT);
14579 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014580 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014581#ifdef FEATURE_WLAN_TDLS
14582 /* First clean up the tdls peers if any */
14583 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14584 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14585 pAdapter->sessionId)
14586 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14587 uint8_t *mac;
14588 mac =
14589 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014590 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014591 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014592 pHddCtx->tdlsConnInfo[staIdx].staId,
14593 pAdapter->sessionId,
14594 MAC_ADDR_ARRAY(mac));
14595 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14596 (pAdapter),
14597 pAdapter->sessionId, mac);
14598 }
14599 }
14600#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014601 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14602 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014603 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14604 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014605 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014606 return -EINVAL;
14607 }
14608 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014609 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014610 pHddStaCtx->conn_info.connState);
14611 }
14612
14613 return status;
14614}
14615
14616/**
14617 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14618 * @wiphy: Pointer to wiphy
14619 * @dev: Pointer to network device
14620 * @reason: Disconnect reason code
14621 *
14622 * Return: 0 for success, non-zero for failure
14623 */
14624static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14625 struct net_device *dev, u16 reason)
14626{
14627 int ret;
14628 cds_ssr_protect(__func__);
14629 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14630 cds_ssr_unprotect(__func__);
14631
14632 return ret;
14633}
14634
14635/**
14636 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14637 * @pAdapter: Pointer to adapter
14638 * @param: Pointer to IBSS parameters
14639 *
14640 * This function is used to initialize the security settings in IBSS mode
14641 *
14642 * Return: 0 for success, non-zero for failure
14643 */
14644static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14645 struct cfg80211_ibss_params
14646 *params)
14647{
14648 int status = 0;
14649 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14650 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14651 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14652
14653 ENTER();
14654
14655 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014656 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014657 pHddStaCtx->ibss_enc_key_installed = 0;
14658
14659 if (params->ie_len && (NULL != params->ie)) {
14660 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14661 params->ie_len, WLAN_EID_RSN)) {
14662 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14663 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14664 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14665 tDot11fIEWPA dot11WPAIE;
14666 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14667 u8 *ie;
14668
14669 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14670 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14671 params->ie_len,
14672 DOT11F_EID_WPA);
14673 if (NULL != ie) {
14674 pWextState->wpaVersion =
14675 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014676 /* Unpack the WPA IE
14677 * Skip past the EID byte and length byte
14678 * and four byte WiFi OUI
14679 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014680 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014681 &ie[2 + 4], ie[1] - 4,
14682 &dot11WPAIE, false);
14683 /*
14684 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014685 * encType for unicast cipher for
14686 * wpa-none is none
14687 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014688 encryptionType =
14689 hdd_translate_wpa_to_csr_encryption_type
14690 (dot11WPAIE.multicast_cipher);
14691 }
14692 }
14693
14694 status =
14695 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14696 params->ie_len);
14697
14698 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014699 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014700 return status;
14701 }
14702 }
14703
14704 pWextState->roamProfile.AuthType.authType[0] =
14705 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14706
14707 if (params->privacy) {
14708 /* Security enabled IBSS, At this time there is no information
14709 * available about the security paramters, so initialise the
14710 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14711 * The correct security parameters will be updated later in
14712 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14713 * set inorder enable privacy bit in beacons
14714 */
14715
14716 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14717 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014718 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014719 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14720 pWextState->roamProfile.EncryptionType.numEntries = 1;
14721 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14722 encryptionType;
14723 return status;
14724}
14725
14726/**
14727 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14728 * @wiphy: Pointer to wiphy
14729 * @dev: Pointer to network device
14730 * @param: Pointer to IBSS join parameters
14731 *
14732 * This function is used to create/join an IBSS network
14733 *
14734 * Return: 0 for success, non-zero for failure
14735 */
14736static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14737 struct net_device *dev,
14738 struct cfg80211_ibss_params *params)
14739{
14740 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14741 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14742 tCsrRoamProfile *pRoamProfile;
14743 int status;
14744 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14745 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014746 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014747 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014748
14749 ENTER();
14750
Anurag Chouhan6d760662016-02-20 16:05:43 +053014751 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014752 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014753 return -EINVAL;
14754 }
14755
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014756 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014757 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014758 return -EINVAL;
14759 }
14760
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014761 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014762 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14763 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014764 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014765 hdd_device_mode_to_string(pAdapter->device_mode),
14766 pAdapter->device_mode);
14767
14768 status = wlan_hdd_validate_context(pHddCtx);
14769
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014770 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014771 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014772
14773 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014774 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014775 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14776 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14777 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14778 int indx;
14779
14780 /* Get channel number */
14781 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014782 params->
14783 chandef.
14784 chan->
14785 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014786
14787 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14788 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014789 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014790 return -EOPNOTSUPP;
14791 }
14792
14793 for (indx = 0; indx < numChans; indx++) {
14794 if (channelNum == validChan[indx]) {
14795 break;
14796 }
14797 }
14798 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014799 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014800 return -EINVAL;
14801 }
14802 }
14803
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014804 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14805 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014806 hdd_err("This concurrency combination is not allowed");
14807 return -ECONNREFUSED;
14808 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014809
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014810 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014811 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014812 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014813
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014814 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14815 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014816 SIR_UPDATE_REASON_JOIN_IBSS);
14817 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014818 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014819 return -EINVAL;
14820 }
14821
14822 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014823 status = policy_mgr_wait_for_connection_update(
14824 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014825 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014826 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014827 return -EINVAL;
14828 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014829 }
14830
14831 /*Try disconnecting if already in connected state */
14832 status = wlan_hdd_try_disconnect(pAdapter);
14833 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014834 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014835 return -EALREADY;
14836 }
14837
14838 pRoamProfile = &pWextState->roamProfile;
14839
14840 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014841 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014842 return -EINVAL;
14843 }
14844
14845 /* enable selected protection checks in IBSS mode */
14846 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14847
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014848 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014849 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14850 pHddCtx->config->
14851 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014852 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014853 }
14854
14855 /* BSSID is provided by upper layers hence no need to AUTO generate */
14856 if (NULL != params->bssid) {
14857 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014858 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014859 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014860 return -EIO;
14861 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014862 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014863 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14864 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014865 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014866 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014867 return -EIO;
14868 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014869 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014870 }
14871 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14872 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14873 pRoamProfile->beaconInterval = params->beacon_interval;
14874 else {
14875 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014876 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014877 params->beacon_interval, pRoamProfile->beaconInterval);
14878 }
14879
14880 /* Set Channel */
14881 if (channelNum) {
14882 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014883 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014884 pRoamProfile->ChannelInfo.numOfChannels = 1;
14885 pHddStaCtx->conn_info.operationChannel = channelNum;
14886 pRoamProfile->ChannelInfo.ChannelList =
14887 &pHddStaCtx->conn_info.operationChannel;
14888 }
14889
14890 /* Initialize security parameters */
14891 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14892 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014893 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014894 return status;
14895 }
14896
14897 /* Issue connect start */
14898 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14899 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014900 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014901 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014902 operationChannel,
14903 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014904
14905 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014906 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014907 return status;
14908 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014909 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014910 return 0;
14911}
14912
14913/**
14914 * wlan_hdd_cfg80211_join_ibss() - join ibss
14915 * @wiphy: Pointer to wiphy
14916 * @dev: Pointer to network device
14917 * @param: Pointer to IBSS join parameters
14918 *
14919 * This function is used to create/join an IBSS network
14920 *
14921 * Return: 0 for success, non-zero for failure
14922 */
14923static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14924 struct net_device *dev,
14925 struct cfg80211_ibss_params *params)
14926{
14927 int ret = 0;
14928
14929 cds_ssr_protect(__func__);
14930 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14931 cds_ssr_unprotect(__func__);
14932
14933 return ret;
14934}
14935
14936/**
14937 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14938 * @wiphy: Pointer to wiphy
14939 * @dev: Pointer to network device
14940 *
14941 * This function is used to leave an IBSS network
14942 *
14943 * Return: 0 for success, non-zero for failure
14944 */
14945static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14946 struct net_device *dev)
14947{
14948 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14949 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14950 tCsrRoamProfile *pRoamProfile;
14951 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14952 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014953 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014954 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014955 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014956
14957 ENTER();
14958
Anurag Chouhan6d760662016-02-20 16:05:43 +053014959 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014960 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014961 return -EINVAL;
14962 }
14963
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014964 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014965 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014966 return -EINVAL;
14967 }
14968
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014969 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014970 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14971 pAdapter->sessionId,
14972 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14973 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014974 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014975 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014976
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014977 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014978 hdd_device_mode_to_string(pAdapter->device_mode),
14979 pAdapter->device_mode);
14980 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014981 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014982 return -EIO;
14983 }
14984
14985 pRoamProfile = &pWextState->roamProfile;
14986
14987 /* Issue disconnect only if interface type is set to IBSS */
14988 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014989 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014990 return -EINVAL;
14991 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014992 /* Clearing add IE of beacon */
14993 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14994 sizeof(tSirMacAddr));
14995 updateIE.smeSessionId = pAdapter->sessionId;
14996 updateIE.ieBufferlength = 0;
14997 updateIE.pAdditionIEBuffer = NULL;
14998 updateIE.append = true;
14999 updateIE.notify = true;
15000 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15001 &updateIE,
15002 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015003 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015004 }
15005
15006 /* Reset WNI_CFG_PROBE_RSP Flags */
15007 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015008
15009 /* Issue Disconnect request */
15010 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15011 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15012 pAdapter->sessionId,
15013 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015014 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015015 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015016 hal_status);
15017 return -EAGAIN;
15018 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015019
15020 /* wait for mc thread to cleanup and then return to upper stack
15021 * so by the time upper layer calls the change interface, we are
15022 * all set to proceed further
15023 */
15024 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15025 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15026 if (!rc) {
15027 hdd_err("Failed to disconnect, timed out");
15028 return -ETIMEDOUT;
15029 }
15030
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015031 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015032 return 0;
15033}
15034
15035/**
15036 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15037 * @wiphy: Pointer to wiphy
15038 * @dev: Pointer to network device
15039 *
15040 * This function is used to leave an IBSS network
15041 *
15042 * Return: 0 for success, non-zero for failure
15043 */
15044static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15045 struct net_device *dev)
15046{
15047 int ret = 0;
15048
15049 cds_ssr_protect(__func__);
15050 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15051 cds_ssr_unprotect(__func__);
15052
15053 return ret;
15054}
15055
15056/**
15057 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15058 * @wiphy: Pointer to wiphy
15059 * @changed: Parameters changed
15060 *
15061 * This function is used to set the phy parameters. RTS Threshold/FRAG
15062 * Threshold/Retry Count etc.
15063 *
15064 * Return: 0 for success, non-zero for failure
15065 */
15066static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15067 u32 changed)
15068{
15069 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15070 tHalHandle hHal = pHddCtx->hHal;
15071 int status;
15072
15073 ENTER();
15074
Anurag Chouhan6d760662016-02-20 16:05:43 +053015075 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015076 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015077 return -EINVAL;
15078 }
15079
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015080 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015081 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15082 NO_SESSION, wiphy->rts_threshold));
15083 status = wlan_hdd_validate_context(pHddCtx);
15084
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015085 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015086 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087
15088 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15089 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15090 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15091
15092 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15093 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015094 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015095 rts_threshold);
15096 return -EINVAL;
15097 }
15098
15099 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15100 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015101 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015102 rts_threshold);
15103 return -EIO;
15104 }
15105
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015106 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015107 }
15108
15109 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15110 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15111 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15112 wiphy->frag_threshold;
15113
15114 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15115 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015116 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015117 frag_threshold);
15118 return -EINVAL;
15119 }
15120
15121 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15122 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015123 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015124 frag_threshold);
15125 return -EIO;
15126 }
15127
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015128 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015129 }
15130
15131 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15132 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15133 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15134 wiphy->retry_short : wiphy->retry_long;
15135
15136 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15137 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015138 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015139 return -EINVAL;
15140 }
15141
15142 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15143 if (0 != sme_cfg_set_int(hHal,
15144 WNI_CFG_LONG_RETRY_LIMIT,
15145 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015146 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015147 retry_value);
15148 return -EIO;
15149 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015150 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015151 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15152 if (0 != sme_cfg_set_int(hHal,
15153 WNI_CFG_SHORT_RETRY_LIMIT,
15154 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015155 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015156 retry_value);
15157 return -EIO;
15158 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015159 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015160 }
15161 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015162 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015163 return 0;
15164}
15165
15166/**
15167 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15168 * @wiphy: Pointer to wiphy
15169 * @changed: Parameters changed
15170 *
15171 * Return: 0 for success, non-zero for failure
15172 */
15173static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15174{
15175 int ret;
15176
15177 cds_ssr_protect(__func__);
15178 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15179 cds_ssr_unprotect(__func__);
15180
15181 return ret;
15182}
15183
15184/**
15185 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15186 * key
15187 * @wiphy: Pointer to wiphy
15188 * @dev: Pointer to network device
15189 * @key_index: Key index
15190 *
15191 * Return: 0
15192 */
15193static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15194 struct net_device *netdev,
15195 u8 key_index)
15196{
15197 ENTER();
15198 return 0;
15199}
15200
15201/**
15202 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15203 * wlan_hdd_set_default_mgmt_key
15204 * @wiphy: pointer to wiphy
15205 * @netdev: pointer to net_device structure
15206 * @key_index: key index
15207 *
15208 * Return: 0 on success, error number on failure
15209 */
15210static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15211 struct net_device *netdev,
15212 u8 key_index)
15213{
15214 int ret;
15215
15216 cds_ssr_protect(__func__);
15217 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15218 cds_ssr_unprotect(__func__);
15219
15220 return ret;
15221}
15222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015223/**
15224 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15225 * @wiphy: Pointer to wiphy
15226 * @dev: Pointer to network device
15227 * @params: Pointer to tx queue parameters
15228 *
15229 * Return: 0
15230 */
15231static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15232 struct net_device *dev,
15233 struct ieee80211_txq_params *params)
15234{
15235 ENTER();
15236 return 0;
15237}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015238
15239/**
15240 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15241 * @wiphy: pointer to wiphy
15242 * @netdev: pointer to net_device structure
15243 * @params: pointer to ieee80211_txq_params
15244 *
15245 * Return: 0 on success, error number on failure
15246 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015247static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15248 struct net_device *dev,
15249 struct ieee80211_txq_params *params)
15250{
15251 int ret;
15252
15253 cds_ssr_protect(__func__);
15254 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15255 cds_ssr_unprotect(__func__);
15256
15257 return ret;
15258}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015259
15260/**
15261 * __wlan_hdd_cfg80211_del_station() - delete station v2
15262 * @wiphy: Pointer to wiphy
15263 * @param: Pointer to delete station parameter
15264 *
15265 * Return: 0 for success, non-zero for failure
15266 */
15267static
15268int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15269 struct net_device *dev,
15270 struct tagCsrDelStaParams *pDelStaParams)
15271{
15272 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15273 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015274 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015275 hdd_hostapd_state_t *hapd_state;
15276 int status;
15277 uint8_t staId;
15278 uint8_t *mac;
15279
15280 ENTER();
15281
Anurag Chouhan6d760662016-02-20 16:05:43 +053015282 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015283 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015284 return -EINVAL;
15285 }
15286
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015287 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015288 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015289 return -EINVAL;
15290 }
15291
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015292 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015293 TRACE_CODE_HDD_CFG80211_DEL_STA,
15294 pAdapter->sessionId, pAdapter->device_mode));
15295
15296 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15297 status = wlan_hdd_validate_context(pHddCtx);
15298
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015299 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015300 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015301
15302 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15303
Krunal Sonib4326f22016-03-10 13:05:51 -080015304 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15305 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015306
15307 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15308 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015309 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015310 return 0;
15311 }
15312
Anurag Chouhanc5548422016-02-24 18:33:27 +053015313 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015314 uint16_t i;
15315 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15316 if ((pAdapter->aStaInfo[i].isUsed) &&
15317 (!pAdapter->aStaInfo[i].
15318 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015319 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015320 mac,
15321 pAdapter->aStaInfo[i].
15322 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015323 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015324 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15325 hdd_ipa_wlan_evt(pAdapter,
15326 pAdapter->
15327 aStaInfo[i].
15328 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015329 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015330 mac);
15331 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015332 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015333 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015334 MAC_ADDR_ARRAY(mac));
15335
15336 if (pHddCtx->dev_dfs_cac_status ==
15337 DFS_CAC_IN_PROGRESS)
15338 goto fn_end;
15339
Wei Song2f76f642016-11-18 16:32:53 +080015340 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015341 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015342 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015343 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015344 hdd_softap_sta_deauth(pAdapter,
15345 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015346 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015347 pAdapter->aStaInfo[i].
15348 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015349 qdf_status =
15350 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015351 &hapd_state->
15352 qdf_sta_disassoc_event,
15353 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015354 if (!QDF_IS_STATUS_SUCCESS(
15355 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015356 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015357 }
15358 }
15359 }
15360 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015361 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015362 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015363 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015364 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015365 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015366 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015367 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015368 MAC_ADDR_ARRAY(mac));
15369 return -ENOENT;
15370 }
15371
15372 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15373 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015374 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015375 }
15376
15377 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15378 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015379 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015380 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015381 MAC_ADDR_ARRAY(mac));
15382 return -ENOENT;
15383 }
15384
15385 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15386
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015387 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015388 MAC_ADDR_ARRAY(mac));
15389
15390 /* Case: SAP in ACS selected DFS ch and client connected
15391 * Now Radar detected. Then if random channel is another
15392 * DFS ch then new CAC is initiated and no TX allowed.
15393 * So do not send any mgmt frames as it will timeout
15394 * during CAC.
15395 */
15396
15397 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15398 goto fn_end;
15399
Wei Song2f76f642016-11-18 16:32:53 +080015400 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015401 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15402 (pAdapter), pAdapter->sessionId,
15403 (uint8_t *)&pDelStaParams->peerMacAddr,
15404 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015405 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015406 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015407 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015408 pAdapter->aStaInfo[staId].isDeauthInProgress =
15409 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015410 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015411 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015412 MAC_ADDR_ARRAY(mac));
15413 return -ENOENT;
15414 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015415 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015416 &hapd_state->
15417 qdf_sta_disassoc_event,
15418 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015419 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015420 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015421 }
15422 }
15423 }
15424
15425fn_end:
15426 EXIT();
15427 return 0;
15428}
15429
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015430#if defined(USE_CFG80211_DEL_STA_V2)
15431/**
15432 * wlan_hdd_del_station() - delete station wrapper
15433 * @adapter: pointer to the hdd adapter
15434 *
15435 * Return: None
15436 */
15437void wlan_hdd_del_station(hdd_adapter_t *adapter)
15438{
15439 struct station_del_parameters del_sta;
15440 del_sta.mac = NULL;
15441 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15442 del_sta.reason_code = eCsrForcedDeauthSta;
15443
15444 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15445 &del_sta);
15446}
15447#else
15448void wlan_hdd_del_station(hdd_adapter_t *adapter)
15449{
15450 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15451}
15452#endif
15453
15454#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015455/**
15456 * wlan_hdd_cfg80211_del_station() - delete station v2
15457 * @wiphy: Pointer to wiphy
15458 * @param: Pointer to delete station parameter
15459 *
15460 * Return: 0 for success, non-zero for failure
15461 */
15462int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15463 struct net_device *dev,
15464 struct station_del_parameters *param)
15465#else
15466/**
15467 * wlan_hdd_cfg80211_del_station() - delete station
15468 * @wiphy: Pointer to wiphy
15469 * @mac: Pointer to station mac address
15470 *
15471 * Return: 0 for success, non-zero for failure
15472 */
15473#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15474int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15475 struct net_device *dev,
15476 const uint8_t *mac)
15477#else
15478int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15479 struct net_device *dev,
15480 uint8_t *mac)
15481#endif
15482#endif
15483{
15484 int ret;
15485 struct tagCsrDelStaParams delStaParams;
15486
15487 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015488#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015489 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015490 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491 return -EINVAL;
15492 }
15493 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15494 param->subtype, &delStaParams);
15495#else
15496 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15497 (SIR_MAC_MGMT_DEAUTH >> 4),
15498 &delStaParams);
15499#endif
15500 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15501 cds_ssr_unprotect(__func__);
15502
15503 return ret;
15504}
15505
15506/**
15507 * __wlan_hdd_cfg80211_add_station() - add station
15508 * @wiphy: Pointer to wiphy
15509 * @mac: Pointer to station mac address
15510 * @pmksa: Pointer to add station parameter
15511 *
15512 * Return: 0 for success, non-zero for failure
15513 */
15514static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15515 struct net_device *dev,
15516 const uint8_t *mac,
15517 struct station_parameters *params)
15518{
15519 int status = -EPERM;
15520#ifdef FEATURE_WLAN_TDLS
15521 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15522 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15523 u32 mask, set;
15524
15525 ENTER();
15526
Anurag Chouhan6d760662016-02-20 16:05:43 +053015527 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015528 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015529 return -EINVAL;
15530 }
15531
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015532 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015533 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015534 return -EINVAL;
15535 }
15536
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015537 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015538 TRACE_CODE_HDD_CFG80211_ADD_STA,
15539 pAdapter->sessionId, params->listen_interval));
15540
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015541 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015542 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015543
15544 mask = params->sta_flags_mask;
15545
15546 set = params->sta_flags_set;
15547
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015548 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015549 MAC_ADDR_ARRAY(mac));
15550
15551 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15552 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015553#if defined(CONVERGED_TDLS_ENABLE)
15554 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15555 dev, mac);
15556#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015557 status =
15558 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015559#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015560 }
15561 }
15562#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015563 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015564 return status;
15565}
15566
15567/**
15568 * wlan_hdd_cfg80211_add_station() - add station
15569 * @wiphy: Pointer to wiphy
15570 * @mac: Pointer to station mac address
15571 * @pmksa: Pointer to add station parameter
15572 *
15573 * Return: 0 for success, non-zero for failure
15574 */
15575#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15576static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15577 struct net_device *dev,
15578 const uint8_t *mac,
15579 struct station_parameters *params)
15580#else
15581static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15582 struct net_device *dev, uint8_t *mac,
15583 struct station_parameters *params)
15584#endif
15585{
15586 int ret;
15587
15588 cds_ssr_protect(__func__);
15589 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15590 cds_ssr_unprotect(__func__);
15591
15592 return ret;
15593}
15594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015595/**
15596 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15597 * @wiphy: Pointer to wiphy
15598 * @dev: Pointer to network device
15599 * @pmksa: Pointer to set pmksa parameter
15600 *
15601 * Return: 0 for success, non-zero for failure
15602 */
15603static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15604 struct net_device *dev,
15605 struct cfg80211_pmksa *pmksa)
15606{
15607 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15608 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15609 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015610 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015611 int status;
15612 tPmkidCacheInfo pmk_id;
15613
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015614 ENTER();
15615
Anurag Chouhan6d760662016-02-20 16:05:43 +053015616 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015617 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015618 return -EINVAL;
15619 }
15620
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015621 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015622 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015623 return -EINVAL;
15624 }
15625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015626 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015627 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015628 return -EINVAL;
15629 }
15630
15631 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015632 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015633 pmksa->bssid, pmksa->pmkid);
15634 return -EINVAL;
15635 }
15636
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015637 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015638 MAC_ADDR_ARRAY(pmksa->bssid));
15639
15640 status = wlan_hdd_validate_context(pHddCtx);
15641
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015642 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015643 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015644
15645 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15646
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015647 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15648 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015649
15650 /* Add to the PMKSA ID Cache in CSR */
15651 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15652 &pmk_id, 1, false);
15653
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015654 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015655 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15656 pAdapter->sessionId, result));
15657
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015658 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015659 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015660}
15661
15662/**
15663 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15664 * @wiphy: Pointer to wiphy
15665 * @dev: Pointer to network device
15666 * @pmksa: Pointer to set pmksa parameter
15667 *
15668 * Return: 0 for success, non-zero for failure
15669 */
15670static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15671 struct net_device *dev,
15672 struct cfg80211_pmksa *pmksa)
15673{
15674 int ret;
15675
15676 cds_ssr_protect(__func__);
15677 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15678 cds_ssr_unprotect(__func__);
15679
15680 return ret;
15681}
15682
15683/**
15684 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15685 * @wiphy: Pointer to wiphy
15686 * @dev: Pointer to network device
15687 * @pmksa: Pointer to pmksa parameter
15688 *
15689 * Return: 0 for success, non-zero for failure
15690 */
15691static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15692 struct net_device *dev,
15693 struct cfg80211_pmksa *pmksa)
15694{
15695 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15696 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15697 tHalHandle halHandle;
15698 int status = 0;
15699
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015700 ENTER();
15701
Anurag Chouhan6d760662016-02-20 16:05:43 +053015702 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015703 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015704 return -EINVAL;
15705 }
15706
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015707 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15708 hdd_err("invalid session id: %d", pAdapter->sessionId);
15709 return -EINVAL;
15710 }
15711
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015712 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015713 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015714 return -EINVAL;
15715 }
15716
15717 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015718 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015719 return -EINVAL;
15720 }
15721
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015722 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015723 MAC_ADDR_ARRAY(pmksa->bssid));
15724
15725 status = wlan_hdd_validate_context(pHddCtx);
15726
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015727 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015728 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015729
15730 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15731
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015732 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015733 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15734 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015735 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015736 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015737 sme_roam_del_pmkid_from_cache(halHandle,
15738 pAdapter->sessionId, pmksa->bssid,
15739 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015740 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015741 MAC_ADDR_ARRAY(pmksa->bssid));
15742 status = -EINVAL;
15743 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015744 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015745 return status;
15746}
15747
15748/**
15749 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15750 * @wiphy: Pointer to wiphy
15751 * @dev: Pointer to network device
15752 * @pmksa: Pointer to pmksa parameter
15753 *
15754 * Return: 0 for success, non-zero for failure
15755 */
15756static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15757 struct net_device *dev,
15758 struct cfg80211_pmksa *pmksa)
15759{
15760 int ret;
15761
15762 cds_ssr_protect(__func__);
15763 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15764 cds_ssr_unprotect(__func__);
15765
15766 return ret;
15767
15768}
15769
15770/**
15771 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15772 * @wiphy: Pointer to wiphy
15773 * @dev: Pointer to network device
15774 *
15775 * Return: 0 for success, non-zero for failure
15776 */
15777static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15778 struct net_device *dev)
15779{
15780 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15781 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15782 tHalHandle halHandle;
15783 int status = 0;
15784
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015785 ENTER();
15786
Anurag Chouhan6d760662016-02-20 16:05:43 +053015787 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015788 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015789 return -EINVAL;
15790 }
15791
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015792 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15793 hdd_err("invalid session id: %d", pAdapter->sessionId);
15794 return -EINVAL;
15795 }
15796
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015797 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015798
15799 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15800 status = wlan_hdd_validate_context(pHddCtx);
15801
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015802 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015803 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015804
15805 /* Retrieve halHandle */
15806 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15807
15808 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015809 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015810 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15811 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015812 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015813 status = -EINVAL;
15814 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015815 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015816 return status;
15817}
15818
15819/**
15820 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15821 * @wiphy: Pointer to wiphy
15822 * @dev: Pointer to network device
15823 *
15824 * Return: 0 for success, non-zero for failure
15825 */
15826static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15827 struct net_device *dev)
15828{
15829 int ret;
15830
15831 cds_ssr_protect(__func__);
15832 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15833 cds_ssr_unprotect(__func__);
15834
15835 return ret;
15836}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015837
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015838#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015839/**
15840 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15841 * @wiphy: Pointer to wiphy
15842 * @dev: Pointer to network device
15843 * @ftie: Pointer to fast transition ie parameter
15844 *
15845 * Return: 0 for success, non-zero for failure
15846 */
15847static int
15848__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15849 struct net_device *dev,
15850 struct cfg80211_update_ft_ies_params *ftie)
15851{
15852 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15853 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15854 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15855 int status;
15856
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015857 ENTER();
15858
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015859 status = wlan_hdd_validate_context(hdd_ctx);
15860 if (status)
15861 return status;
15862
Anurag Chouhan6d760662016-02-20 16:05:43 +053015863 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015864 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015865 return -EINVAL;
15866 }
15867
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015868 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15869 hdd_err("invalid session id: %d", pAdapter->sessionId);
15870 return -EINVAL;
15871 }
15872
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015873 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015874 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15875 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15876 /* Added for debug on reception of Re-assoc Req. */
15877 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015878 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015879 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015880 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015881 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015882 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015883 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015884
15885 /* Pass the received FT IEs to SME */
15886 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15887 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015888 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015889 return 0;
15890}
15891
15892/**
15893 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15894 * @wiphy: Pointer to wiphy
15895 * @dev: Pointer to network device
15896 * @ftie: Pointer to fast transition ie parameter
15897 *
15898 * Return: 0 for success, non-zero for failure
15899 */
15900static int
15901wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15902 struct net_device *dev,
15903 struct cfg80211_update_ft_ies_params *ftie)
15904{
15905 int ret;
15906
15907 cds_ssr_protect(__func__);
15908 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15909 cds_ssr_unprotect(__func__);
15910
15911 return ret;
15912}
15913#endif
15914
Mukul Sharma3d36c392017-01-18 18:39:12 +053015915void wlan_hdd_cfg80211_update_replay_counter_callback(
15916 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15917
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015918{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015919 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15920 uint8_t temp_replay_counter[8];
15921 int i;
15922 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015923
15924 ENTER();
15925
Mukul Sharma3d36c392017-01-18 18:39:12 +053015926 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015927 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015928 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015929 }
15930
Mukul Sharma3d36c392017-01-18 18:39:12 +053015931 if (!gtk_rsp_param) {
15932 hdd_err("gtk_rsp_param is Null");
15933 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015934 }
15935
Mukul Sharma3d36c392017-01-18 18:39:12 +053015936 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015937 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015938 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015939 }
15940
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015941 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015942 gtk_rsp_param->replay_counter);
15943 /* convert little to big endian since supplicant works on big endian */
15944 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15945 for (i = 0; i < 8; i++)
15946 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015947
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015948 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015949 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015950 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015951 gtk_rsp_param->bssid.bytes,
15952 temp_replay_counter, GFP_KERNEL);
15953out:
15954 EXIT();
15955
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015956}
15957
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015958static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015959int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015960 struct net_device *dev,
15961 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015962{
15963 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015964 int result, i;
15965 struct pmo_gtk_req *gtk_req = NULL;
15966 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15967 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015968 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015969
15970 ENTER();
15971
Anurag Chouhan6d760662016-02-20 16:05:43 +053015972 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015973 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015974 result = -EINVAL;
15975 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015976 }
15977
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015978 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15979 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015980 result = -EINVAL;
15981 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015982 }
15983
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015984 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015985 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15986 pAdapter->sessionId, pAdapter->device_mode));
15987
Mukul Sharma3d36c392017-01-18 18:39:12 +053015988 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015989 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015990 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015991
Mukul Sharma3d36c392017-01-18 18:39:12 +053015992 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15993 if (!gtk_req) {
15994 hdd_err("cannot allocate gtk_req");
15995 result = -ENOMEM;
15996 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015997 }
15998
Mukul Sharma3d36c392017-01-18 18:39:12 +053015999 /* convert big to little endian since driver work on little endian */
16000 buf = (uint8_t *)&gtk_req->replay_counter;
16001 for (i = 0; i < 8; i++)
16002 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016003
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016004 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016005 gtk_req->replay_counter);
16006 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16007 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16008 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16009 if (status != QDF_STATUS_SUCCESS) {
16010 hdd_err("Failed to cache GTK Offload");
16011 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016012 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016013out:
16014 if (gtk_req)
16015 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016016 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016017
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016018 return result;
16019}
16020
16021/**
16022 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16023 * @wiphy: Pointer to wiphy
16024 * @dev: Pointer to network device
16025 * @data: Pointer to rekey data
16026 *
16027 * This function is used to offload GTK rekeying job to the firmware.
16028 *
16029 * Return: 0 for success, non-zero for failure
16030 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016031static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016032int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16033 struct net_device *dev,
16034 struct cfg80211_gtk_rekey_data *data)
16035{
16036 int ret;
16037
16038 cds_ssr_protect(__func__);
16039 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16040 cds_ssr_unprotect(__func__);
16041
16042 return ret;
16043}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016044
16045/**
16046 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16047 * @wiphy: Pointer to wiphy
16048 * @dev: Pointer to network device
16049 * @param: Pointer to access control parameter
16050 *
16051 * Return: 0 for success, non-zero for failure
16052 */
16053static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16054 struct net_device *dev,
16055 const struct cfg80211_acl_data *params)
16056{
16057 int i;
16058 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16059 hdd_hostapd_state_t *pHostapdState;
16060 tsap_Config_t *pConfig;
16061 v_CONTEXT_t p_cds_context = NULL;
16062 hdd_context_t *pHddCtx;
16063 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016064 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016065
16066 ENTER();
16067
Anurag Chouhan6d760662016-02-20 16:05:43 +053016068 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016069 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016070 return -EINVAL;
16071 }
16072
16073 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016074 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016075 return -EINVAL;
16076 }
16077
16078 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16079 status = wlan_hdd_validate_context(pHddCtx);
16080
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016081 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016082 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016083
16084 p_cds_context = pHddCtx->pcds_context;
16085 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16086
16087 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016088 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016089 return -EINVAL;
16090 }
16091
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016092 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016093 params->n_acl_entries);
16094
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016095 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016096 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16097 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016098 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016099 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16100
16101 /* default value */
16102 pConfig->num_accept_mac = 0;
16103 pConfig->num_deny_mac = 0;
16104
16105 /**
16106 * access control policy
16107 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16108 * listed in hostapd.deny file.
16109 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16110 * listed in hostapd.accept file.
16111 */
16112 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16113 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16114 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16115 params->acl_policy) {
16116 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16117 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016118 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016119 params->acl_policy);
16120 return -ENOTSUPP;
16121 }
16122
16123 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16124 pConfig->num_accept_mac = params->n_acl_entries;
16125 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016126 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016127 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016128 MAC_ADDR_ARRAY(
16129 params->mac_addrs[i].addr));
16130
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016131 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016132 params->mac_addrs[i].addr,
16133 sizeof(qcmacaddr));
16134 }
16135 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16136 pConfig->num_deny_mac = params->n_acl_entries;
16137 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016138 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016139 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016140 MAC_ADDR_ARRAY(
16141 params->mac_addrs[i].addr));
16142
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016143 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016144 params->mac_addrs[i].addr,
16145 sizeof(qcmacaddr));
16146 }
16147 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016148 qdf_status = wlansap_set_mac_acl(
16149 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016150 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016151 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016152 return -EINVAL;
16153 }
16154 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016155 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016156 hdd_device_mode_to_string(pAdapter->device_mode),
16157 pAdapter->device_mode);
16158 return -EINVAL;
16159 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016160 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016161 return 0;
16162}
16163
16164/**
16165 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16166 * __wlan_hdd_cfg80211_set_mac_acl
16167 * @wiphy: pointer to wiphy structure
16168 * @dev: pointer to net_device
16169 * @params: pointer to cfg80211_acl_data
16170 *
16171 * Return; 0 on success, error number otherwise
16172 */
16173static int
16174wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16175 struct net_device *dev,
16176 const struct cfg80211_acl_data *params)
16177{
16178 int ret;
16179
16180 cds_ssr_protect(__func__);
16181 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16182 cds_ssr_unprotect(__func__);
16183
16184 return ret;
16185}
16186
16187#ifdef WLAN_NL80211_TESTMODE
16188#ifdef FEATURE_WLAN_LPHB
16189/**
16190 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16191 * @pHddCtx: Pointer to hdd context
16192 * @lphbInd: Pointer to low power heart beat indication parameter
16193 *
16194 * Return: none
16195 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016196static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016197 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016198{
16199 struct sk_buff *skb;
16200
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016201 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016202
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016203 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016204 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016205
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016206 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016207 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016208 return;
16209 }
16210
16211 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016212 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016213 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016214 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016215 return;
16216 }
16217
16218 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016219 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016220 goto nla_put_failure;
16221 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016222 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016223 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016224 goto nla_put_failure;
16225 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016226 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16227 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016228 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016229 goto nla_put_failure;
16230 }
16231 cfg80211_testmode_event(skb, GFP_ATOMIC);
16232 return;
16233
16234nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016235 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016236 kfree_skb(skb);
16237
16238 return;
16239}
16240#endif /* FEATURE_WLAN_LPHB */
16241
16242/**
16243 * __wlan_hdd_cfg80211_testmode() - test mode
16244 * @wiphy: Pointer to wiphy
16245 * @data: Data pointer
16246 * @len: Data length
16247 *
16248 * Return: 0 for success, non-zero for failure
16249 */
16250static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16251 void *data, int len)
16252{
16253 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16254 int err;
16255 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16256
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016257 ENTER();
16258
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016259 err = wlan_hdd_validate_context(pHddCtx);
16260 if (err)
16261 return err;
16262
16263 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16264 len, wlan_hdd_tm_policy);
16265 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016266 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016267 return err;
16268 }
16269
16270 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016271 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016272 return -EINVAL;
16273 }
16274
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016275 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016276 TRACE_CODE_HDD_CFG80211_TESTMODE,
16277 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016278 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16279#ifdef FEATURE_WLAN_LPHB
16280 /* Low Power Heartbeat configuration request */
16281 case WLAN_HDD_TM_CMD_WLAN_HB:
16282 {
16283 int buf_len;
16284 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016285 struct pmo_lphb_req *hb_params = NULL;
16286 struct pmo_lphb_req *hb_params_temp = NULL;
16287 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016288
16289 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016290 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016291 return -EINVAL;
16292 }
16293
16294 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16295 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16296
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016297 hb_params_temp = (struct pmo_lphb_req *) buf;
16298 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16299 && (hb_params_temp->params.lphb_tcp_params.
16300 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016301 return -EINVAL;
16302
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016303 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16304 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016305 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016306 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016307 return -ENOMEM;
16308 }
16309
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016310 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016311 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16312 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016313 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016314 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016315 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016316
16317 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016318 return 0;
16319 }
16320#endif /* FEATURE_WLAN_LPHB */
16321
16322#if defined(QCA_WIFI_FTM)
16323 case WLAN_HDD_TM_CMD_WLAN_FTM:
16324 {
16325 int buf_len;
16326 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016327 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016328 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016329 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016330 return -EINVAL;
16331 }
16332
16333 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16334 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16335
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016336 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016337
16338 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16339
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016340 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016341 err = -EBUSY;
16342 break;
16343 }
16344#endif
16345
16346 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016347 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016348 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16349 return -EOPNOTSUPP;
16350 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016351 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016352 return err;
16353}
16354
16355/**
16356 * wlan_hdd_cfg80211_testmode() - test mode
16357 * @wiphy: Pointer to wiphy
16358 * @dev: Pointer to network device
16359 * @data: Data pointer
16360 * @len: Data length
16361 *
16362 * Return: 0 for success, non-zero for failure
16363 */
16364static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16365#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16366 struct wireless_dev *wdev,
16367#endif
16368 void *data, int len)
16369{
16370 int ret;
16371
16372 cds_ssr_protect(__func__);
16373 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16374 cds_ssr_unprotect(__func__);
16375
16376 return ret;
16377}
16378
16379#if defined(QCA_WIFI_FTM)
16380/**
16381 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16382 * @buf: Pointer to buffer
16383 * @buf_len: Buffer length
16384 *
16385 * Return: none
16386 */
16387void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16388{
16389 struct sk_buff *skb;
16390 hdd_context_t *hdd_ctx;
16391
16392 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016393 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016394 return;
16395 }
16396
Anurag Chouhan6d760662016-02-20 16:05:43 +053016397 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016398 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016399 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016400 return;
16401 }
16402
16403 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16404 buf_len, GFP_KERNEL);
16405 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016406 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016407 return;
16408 }
16409
16410 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16411 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16412 goto nla_put_failure;
16413
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016414 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016415
16416 cfg80211_testmode_event(skb, GFP_KERNEL);
16417 return;
16418
16419nla_put_failure:
16420 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016421 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016422}
16423#endif
16424#endif /* CONFIG_NL80211_TESTMODE */
16425
16426#ifdef QCA_HT_2040_COEX
16427/**
16428 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16429 * @wiphy: Pointer to wiphy
16430 * @dev: Pointer to network device
16431 * @chandef: Pointer to channel definition parameter
16432 *
16433 * Return: 0 for success, non-zero for failure
16434 */
16435static int
16436__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16437 struct net_device *dev,
16438 struct cfg80211_chan_def *chandef)
16439{
16440 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16441 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016442 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016443 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016444 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016445
Anurag Chouhan6d760662016-02-20 16:05:43 +053016446 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016447 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016448 return -EINVAL;
16449 }
16450
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016451 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16452 hdd_err("invalid session id: %d", pAdapter->sessionId);
16453 return -EINVAL;
16454 }
16455
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016456 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16457 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016458 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016459 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016460
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016461 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016462 sme_get_config_param(pHddCtx->hHal, &sme_config);
16463 switch (chandef->width) {
16464 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016465 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016466 if (sme_config.csrConfig.channelBondingMode24GHz !=
16467 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16468 sme_config.csrConfig.channelBondingMode24GHz =
16469 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16470 sme_update_config(pHddCtx->hHal, &sme_config);
16471 cbModeChange = true;
16472 }
16473 break;
16474
16475 case NL80211_CHAN_WIDTH_40:
16476 if (sme_config.csrConfig.channelBondingMode24GHz ==
16477 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16478 if (NL80211_CHAN_HT40MINUS ==
16479 cfg80211_get_chandef_type(chandef))
16480 sme_config.csrConfig.channelBondingMode24GHz =
16481 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16482 else
16483 sme_config.csrConfig.channelBondingMode24GHz =
16484 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16485 sme_update_config(pHddCtx->hHal, &sme_config);
16486 cbModeChange = true;
16487 }
16488 break;
16489
16490 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016491 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016492 return -EINVAL;
16493 }
16494
16495 if (!cbModeChange)
16496 return 0;
16497
Krunal Sonib4326f22016-03-10 13:05:51 -080016498 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016499 return 0;
16500
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016501 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016502 sme_config.csrConfig.channelBondingMode24GHz);
16503
16504 /* Change SAP ht2040 mode */
16505 status = hdd_set_sap_ht2040_mode(pAdapter,
16506 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016507 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016508 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016509 return -EINVAL;
16510 }
16511
16512 return 0;
16513}
16514
16515/**
16516 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16517 * @wiphy: Pointer to wiphy
16518 * @dev: Pointer to network device
16519 * @chandef: Pointer to channel definition parameter
16520 *
16521 * Return: 0 for success, non-zero for failure
16522 */
16523static int
16524wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16525 struct net_device *dev,
16526 struct cfg80211_chan_def *chandef)
16527{
16528 int ret;
16529
16530 cds_ssr_protect(__func__);
16531 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16532 cds_ssr_unprotect(__func__);
16533
16534 return ret;
16535}
16536#endif
16537
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016538#ifdef CHANNEL_SWITCH_SUPPORTED
16539/**
16540 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16541 * channel in SAP/GO
16542 * @wiphy: wiphy pointer
16543 * @dev: dev pointer.
16544 * @csa_params: Change channel params
16545 *
16546 * This function is called to switch channel in SAP/GO
16547 *
16548 * Return: 0 if success else return non zero
16549 */
16550static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16551 struct net_device *dev,
16552 struct cfg80211_csa_settings *csa_params)
16553{
16554 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16555 hdd_context_t *hdd_ctx;
16556 uint8_t channel;
16557 uint16_t freq;
16558 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016559 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016560
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016561 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016562 csa_params->chandef.chan->center_freq);
16563
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016564 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16565 hdd_err("invalid session id: %d", adapter->sessionId);
16566 return -EINVAL;
16567 }
16568
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016569 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16570 ret = wlan_hdd_validate_context(hdd_ctx);
16571
16572 if (0 != ret)
16573 return ret;
16574
Krunal Sonib4326f22016-03-10 13:05:51 -080016575 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16576 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016577 return -ENOTSUPP;
16578
16579 freq = csa_params->chandef.chan->center_freq;
16580 channel = cds_freq_to_chan(freq);
16581
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016582 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16583
16584 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016585 return ret;
16586}
16587
16588/**
16589 * wlan_hdd_cfg80211_channel_switch()- function to switch
16590 * channel in SAP/GO
16591 * @wiphy: wiphy pointer
16592 * @dev: dev pointer.
16593 * @csa_params: Change channel params
16594 *
16595 * This function is called to switch channel in SAP/GO
16596 *
16597 * Return: 0 if success else return non zero
16598 */
16599static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16600 struct net_device *dev,
16601 struct cfg80211_csa_settings *csa_params)
16602{
16603 int ret;
16604
16605 cds_ssr_protect(__func__);
16606 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16607 cds_ssr_unprotect(__func__);
16608 return ret;
16609}
16610#endif
16611
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016612/**
16613 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16614 * translation from NL to policy manager type
16615 * @type: Generic connection mode type defined in NL
16616 *
16617 *
16618 * This function provides the type translation
16619 *
16620 * Return: cds_con_mode enum
16621 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016622enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016623 enum nl80211_iftype type)
16624{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016625 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016626 switch (type) {
16627 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016628 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016629 break;
16630 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016631 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016632 break;
16633 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016634 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016635 break;
16636 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016637 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016638 break;
16639 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016640 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016641 break;
16642 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016643 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016644 }
16645 return mode;
16646}
16647
16648/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016649 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16650 * @wiphy: Handle to struct wiphy to get handle to module context.
16651 * @chandef: Contains information about the capture channel to be set.
16652 *
16653 * This interface is called if and only if monitor mode interface alone is
16654 * active.
16655 *
16656 * Return: 0 success or error code on failure.
16657 */
16658static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16659 struct cfg80211_chan_def *chandef)
16660{
16661 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16662 hdd_adapter_t *adapter;
16663 hdd_station_ctx_t *sta_ctx;
16664 struct hdd_mon_set_ch_info *ch_info;
16665 QDF_STATUS status;
16666 tHalHandle hal_hdl;
16667 struct qdf_mac_addr bssid;
16668 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016669 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016670 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016671 int ret;
16672 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16673
16674 ENTER();
16675
16676 ret = wlan_hdd_validate_context(hdd_ctx);
16677 if (ret)
16678 return ret;
16679
16680 hal_hdl = hdd_ctx->hHal;
16681
16682 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16683 if (!adapter)
16684 return -EIO;
16685
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016686 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016687 adapter->dev->name, chan_num, chandef->chan->center_freq);
16688
16689 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16690 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016691 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16692 roam_profile.ChannelInfo.numOfChannels = 1;
16693 roam_profile.phyMode = ch_info->phy_mode;
16694 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016695 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016696
16697 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16698 QDF_MAC_ADDR_SIZE);
16699
16700 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016701 /*
16702 * CDS api expects secondary channel for calculating
16703 * the channel params
16704 */
16705 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016706 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016707 if (chan_num >= 1 && chan_num <= 5)
16708 sec_ch = chan_num + 4;
16709 else if (chan_num >= 6 && chan_num <= 13)
16710 sec_ch = chan_num - 4;
16711 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016712 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
16713 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016714 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16715 &roam_profile);
16716 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016717 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016718 status);
16719 ret = qdf_status_to_os_return(status);
16720 return ret;
16721 }
16722 EXIT();
16723 return 0;
16724}
16725
16726/**
16727 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16728 * @wiphy: Handle to struct wiphy to get handle to module context.
16729 * @chandef: Contains information about the capture channel to be set.
16730 *
16731 * This interface is called if and only if monitor mode interface alone is
16732 * active.
16733 *
16734 * Return: 0 success or error code on failure.
16735 */
16736static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16737 struct cfg80211_chan_def *chandef)
16738{
16739 int ret;
16740
16741 cds_ssr_protect(__func__);
16742 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16743 cds_ssr_unprotect(__func__);
16744 return ret;
16745}
16746
16747/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016748 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16749 * @adapter: pointer to adapter
16750 *
16751 * Wrapper function to clear link layer stats.
16752 * return - void
16753 */
16754void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16755{
16756 tSirLLStatsClearReq link_layer_stats_clear_req;
16757 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16758
Mukul Sharma491021c2016-09-29 21:39:19 +053016759 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16760 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016761 link_layer_stats_clear_req.stopReq = 0;
16762 link_layer_stats_clear_req.reqId = 1;
16763 link_layer_stats_clear_req.staId = adapter->sessionId;
16764 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16765
16766 return;
16767}
16768
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016769/**
16770 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16771 * @adapter: HDD Adapter
16772 *
16773 * If roaming is in progress and there is a request to
16774 * disconnect the session, then it is deferred. Once
16775 * roaming is complete/aborted, then this routine is
16776 * used to resume the disconnect that was deferred
16777 *
16778 * Return: None
16779 */
16780void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16781{
16782 switch (adapter->defer_disconnect) {
16783 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16784 adapter->defer_disconnect = 0;
16785 wlan_hdd_disconnect(adapter,
16786 adapter->cfg80211_disconnect_reason);
16787 break;
16788 case DEFER_DISCONNECT_TRY_DISCONNECT:
16789 wlan_hdd_try_disconnect(adapter);
16790 adapter->defer_disconnect = 0;
16791 break;
16792 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016793 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016794 adapter->defer_disconnect);
16795 break;
16796 }
16797}
16798
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016799#define CNT_DIFF(cur, prev) \
16800 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16801#define MAX_COUNT 0xffffffff
16802static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16803 struct scan_chan_info *chan,
16804 struct scan_chan_info *info, uint32_t cmd_flag)
16805{
16806 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16807 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16808 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16809
16810 mutex_lock(&hdd_ctx->chan_info_lock);
16811
16812 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16813 qdf_mem_zero(chan, sizeof(*chan));
16814
16815 chan->freq = info->freq;
16816 chan->noise_floor = info->noise_floor;
16817 chan->clock_freq = info->clock_freq;
16818 chan->cmd_flag = info->cmd_flag;
16819 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16820
16821 chan->rx_clear_count =
16822 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16823
16824 chan->tx_frame_count =
16825 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16826
16827 mutex_unlock(&hdd_ctx->chan_info_lock);
16828
16829}
16830#undef CNT_DIFF
16831#undef MAX_COUNT
16832
16833/**
16834 * wlan_hdd_chan_info_cb() - channel info callback
16835 * @chan_info: struct scan_chan_info
16836 *
16837 * Store channel info into HDD context
16838 *
16839 * Return: None.
16840 */
16841static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16842{
16843 hdd_context_t *hdd_ctx;
16844 struct scan_chan_info *chan;
16845 uint8_t idx;
16846
16847 ENTER();
16848
16849 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16850 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16851 hdd_err("hdd_ctx is invalid");
16852 return;
16853 }
16854
16855 if (!hdd_ctx->chan_info) {
16856 hdd_err("chan_info is NULL");
16857 return;
16858 }
16859
16860 chan = hdd_ctx->chan_info;
16861 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16862 if (chan[idx].freq == info->freq) {
16863 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16864 info->cmd_flag);
16865 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16866 chan[idx].cmd_flag, chan[idx].freq,
16867 chan[idx].noise_floor,
16868 chan[idx].cycle_count, chan[idx].rx_clear_count,
16869 chan[idx].clock_freq, chan[idx].cmd_flag,
16870 chan[idx].tx_frame_count, idx);
16871 if (chan[idx].freq == 0)
16872 break;
16873
16874 }
16875 }
16876
16877 EXIT();
16878}
16879
16880/**
16881 * wlan_hdd_init_chan_info() - init chan info in hdd context
16882 * @hdd_ctx: HDD context pointer
16883 *
16884 * Return: none
16885 */
16886void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16887{
16888 uint8_t num_2g, num_5g, index = 0;
16889
16890 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16891 hdd_info("SNR monitoring is disabled");
16892 return;
16893 }
16894
16895 hdd_ctx->chan_info =
16896 qdf_mem_malloc(sizeof(struct scan_chan_info)
16897 * QDF_MAX_NUM_CHAN);
16898 if (hdd_ctx->chan_info == NULL) {
16899 hdd_err("Failed to malloc for chan info");
16900 return;
16901 }
16902 mutex_init(&hdd_ctx->chan_info_lock);
16903
16904 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16905 for (; index < num_2g; index++) {
16906 hdd_ctx->chan_info[index].freq =
16907 hdd_channels_2_4_ghz[index].center_freq;
16908 }
16909
16910 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16911 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016912 if (WLAN_REG_IS_11P_CH(
16913 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016914 continue;
16915 hdd_ctx->chan_info[index].freq =
16916 hdd_channels_5_ghz[index - num_2g].center_freq;
16917 }
16918 sme_set_chan_info_callback(hdd_ctx->hHal,
16919 &wlan_hdd_chan_info_cb);
16920}
16921
16922/**
16923 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16924 * @hdd_ctx: hdd context pointer
16925 *
16926 * Return: none
16927 */
16928void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16929{
16930 struct scan_chan_info *chan;
16931
16932 chan = hdd_ctx->chan_info;
16933 hdd_ctx->chan_info = NULL;
16934 if (chan)
16935 qdf_mem_free(chan);
16936}
16937
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016938/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016939 * struct cfg80211_ops - cfg80211_ops
16940 *
16941 * @add_virtual_intf: Add virtual interface
16942 * @del_virtual_intf: Delete virtual interface
16943 * @change_virtual_intf: Change virtual interface
16944 * @change_station: Change station
16945 * @add_beacon: Add beacon in sap mode
16946 * @del_beacon: Delete beacon in sap mode
16947 * @set_beacon: Set beacon in sap mode
16948 * @start_ap: Start ap
16949 * @change_beacon: Change beacon
16950 * @stop_ap: Stop ap
16951 * @change_bss: Change bss
16952 * @add_key: Add key
16953 * @get_key: Get key
16954 * @del_key: Delete key
16955 * @set_default_key: Set default key
16956 * @set_channel: Set channel
16957 * @scan: Scan
16958 * @connect: Connect
16959 * @disconnect: Disconnect
16960 * @join_ibss = Join ibss
16961 * @leave_ibss = Leave ibss
16962 * @set_wiphy_params = Set wiphy params
16963 * @set_tx_power = Set tx power
16964 * @get_tx_power = get tx power
16965 * @remain_on_channel = Remain on channel
16966 * @cancel_remain_on_channel = Cancel remain on channel
16967 * @mgmt_tx = Tx management frame
16968 * @mgmt_tx_cancel_wait = Cancel management tx wait
16969 * @set_default_mgmt_key = Set default management key
16970 * @set_txq_params = Set tx queue parameters
16971 * @get_station = Get station
16972 * @set_power_mgmt = Set power management
16973 * @del_station = Delete station
16974 * @add_station = Add station
16975 * @set_pmksa = Set pmksa
16976 * @del_pmksa = Delete pmksa
16977 * @flush_pmksa = Flush pmksa
16978 * @update_ft_ies = Update FT IEs
16979 * @tdls_mgmt = Tdls management
16980 * @tdls_oper = Tdls operation
16981 * @set_rekey_data = Set rekey data
16982 * @sched_scan_start = Scheduled scan start
16983 * @sched_scan_stop = Scheduled scan stop
16984 * @resume = Resume wlan
16985 * @suspend = Suspend wlan
16986 * @set_mac_acl = Set mac acl
16987 * @testmode_cmd = Test mode command
16988 * @set_ap_chanwidth = Set AP channel bandwidth
16989 * @dump_survey = Dump survey
16990 * @key_mgmt_set_pmk = Set pmk key management
16991 */
16992static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16993 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16994 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16995 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16996 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016997 .start_ap = wlan_hdd_cfg80211_start_ap,
16998 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16999 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017000 .change_bss = wlan_hdd_cfg80211_change_bss,
17001 .add_key = wlan_hdd_cfg80211_add_key,
17002 .get_key = wlan_hdd_cfg80211_get_key,
17003 .del_key = wlan_hdd_cfg80211_del_key,
17004 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17005 .scan = wlan_hdd_cfg80211_scan,
17006 .connect = wlan_hdd_cfg80211_connect,
17007 .disconnect = wlan_hdd_cfg80211_disconnect,
17008 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17009 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17010 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17011 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17012 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17013 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17014 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17015 .mgmt_tx = wlan_hdd_mgmt_tx,
17016 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17017 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17018 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017019 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017020 .get_station = wlan_hdd_cfg80211_get_station,
17021 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17022 .del_station = wlan_hdd_cfg80211_del_station,
17023 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017024 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17025 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17026 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017027#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017028 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17029#endif
17030#ifdef FEATURE_WLAN_TDLS
17031 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17032 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17033#endif
17034#ifdef WLAN_FEATURE_GTK_OFFLOAD
17035 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17036#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17037#ifdef FEATURE_WLAN_SCAN_PNO
17038 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17039 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17040#endif /*FEATURE_WLAN_SCAN_PNO */
17041 .resume = wlan_hdd_cfg80211_resume_wlan,
17042 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17043 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17044#ifdef WLAN_NL80211_TESTMODE
17045 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17046#endif
17047#ifdef QCA_HT_2040_COEX
17048 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17049#endif
17050 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017051#ifdef CHANNEL_SWITCH_SUPPORTED
17052 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17053#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017054 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017055#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17056 defined(CFG80211_ABORT_SCAN)
17057 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17058#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017059};