blob: eec23f52f1449e9e9e69155cb6a67f93036e2a21 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080081#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080082#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083
84#ifdef FEATURE_WLAN_EXTSCAN
85#include "wlan_hdd_ext_scan.h"
86#endif
87
88#ifdef WLAN_FEATURE_LINK_LAYER_STATS
89#include "wlan_hdd_stats.h"
90#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080091#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080092#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#include "qwlan_version.h"
94#include "wlan_hdd_memdump.h"
95
96#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070097#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +0530100#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700101#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700102#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530103#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800104#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800105#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800106
Leo Changfdb45c32016-10-28 11:09:23 -0700107#include <cdp_txrx_cmn.h>
108#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800109#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530110#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800111#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530112#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700113#include "wlan_reg_ucfg_api.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115#define g_mode_rates_size (12)
116#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800117#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
118 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
119
120/*
121 * Android CTS verifier needs atleast this much wait time (in msec)
122 */
123#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
124
125/*
126 * Refer @tCfgProtection structure for definition of the bit map.
127 * below value is obtained by setting the following bit-fields.
128 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
129 */
130#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
131
132#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700133 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134 .center_freq = (freq), \
135 .hw_value = (chan), \
136 .flags = (flag), \
137 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800138 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139}
140
141#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700142 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143 .center_freq = (freq), \
144 .hw_value = (chan), \
145 .flags = (flag), \
146 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800147 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148}
149
150#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
151 { \
152 .bitrate = rate, \
153 .hw_value = rate_id, \
154 .flags = flag, \
155 }
156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
158#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159
160#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800161
Agrawal Ashish65634612016-08-18 13:24:32 +0530162#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
163 mode <= DFS_MODE_DEPRIORITIZE))
164#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
165 || (channel >= 36 && channel <= 184))
166
Peng Xu4d67c8f2015-10-16 16:02:26 -0700167#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530168#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700169
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170static const u32 hdd_cipher_suites[] = {
171 WLAN_CIPHER_SUITE_WEP40,
172 WLAN_CIPHER_SUITE_WEP104,
173 WLAN_CIPHER_SUITE_TKIP,
174#ifdef FEATURE_WLAN_ESE
175#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
176#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
177 WLAN_CIPHER_SUITE_BTK,
178 WLAN_CIPHER_SUITE_KRK,
179 WLAN_CIPHER_SUITE_CCMP,
180#else
181 WLAN_CIPHER_SUITE_CCMP,
182#endif
183#ifdef FEATURE_WLAN_WAPI
184 WLAN_CIPHER_SUITE_SMS4,
185#endif
186#ifdef WLAN_FEATURE_11W
187 WLAN_CIPHER_SUITE_AES_CMAC,
188#endif
189};
190
Abhishek Singhf512bf32016-05-04 16:47:46 +0530191static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192 HDD2GHZCHAN(2412, 1, 0),
193 HDD2GHZCHAN(2417, 2, 0),
194 HDD2GHZCHAN(2422, 3, 0),
195 HDD2GHZCHAN(2427, 4, 0),
196 HDD2GHZCHAN(2432, 5, 0),
197 HDD2GHZCHAN(2437, 6, 0),
198 HDD2GHZCHAN(2442, 7, 0),
199 HDD2GHZCHAN(2447, 8, 0),
200 HDD2GHZCHAN(2452, 9, 0),
201 HDD2GHZCHAN(2457, 10, 0),
202 HDD2GHZCHAN(2462, 11, 0),
203 HDD2GHZCHAN(2467, 12, 0),
204 HDD2GHZCHAN(2472, 13, 0),
205 HDD2GHZCHAN(2484, 14, 0),
206};
207
Abhishek Singhf512bf32016-05-04 16:47:46 +0530208static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209 HDD5GHZCHAN(5180, 36, 0),
210 HDD5GHZCHAN(5200, 40, 0),
211 HDD5GHZCHAN(5220, 44, 0),
212 HDD5GHZCHAN(5240, 48, 0),
213 HDD5GHZCHAN(5260, 52, 0),
214 HDD5GHZCHAN(5280, 56, 0),
215 HDD5GHZCHAN(5300, 60, 0),
216 HDD5GHZCHAN(5320, 64, 0),
217 HDD5GHZCHAN(5500, 100, 0),
218 HDD5GHZCHAN(5520, 104, 0),
219 HDD5GHZCHAN(5540, 108, 0),
220 HDD5GHZCHAN(5560, 112, 0),
221 HDD5GHZCHAN(5580, 116, 0),
222 HDD5GHZCHAN(5600, 120, 0),
223 HDD5GHZCHAN(5620, 124, 0),
224 HDD5GHZCHAN(5640, 128, 0),
225 HDD5GHZCHAN(5660, 132, 0),
226 HDD5GHZCHAN(5680, 136, 0),
227 HDD5GHZCHAN(5700, 140, 0),
228 HDD5GHZCHAN(5720, 144, 0),
229 HDD5GHZCHAN(5745, 149, 0),
230 HDD5GHZCHAN(5765, 153, 0),
231 HDD5GHZCHAN(5785, 157, 0),
232 HDD5GHZCHAN(5805, 161, 0),
233 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800234 HDD5GHZCHAN(5852, 170, 0),
235 HDD5GHZCHAN(5855, 171, 0),
236 HDD5GHZCHAN(5860, 172, 0),
237 HDD5GHZCHAN(5865, 173, 0),
238 HDD5GHZCHAN(5870, 174, 0),
239 HDD5GHZCHAN(5875, 175, 0),
240 HDD5GHZCHAN(5880, 176, 0),
241 HDD5GHZCHAN(5885, 177, 0),
242 HDD5GHZCHAN(5890, 178, 0),
243 HDD5GHZCHAN(5895, 179, 0),
244 HDD5GHZCHAN(5900, 180, 0),
245 HDD5GHZCHAN(5905, 181, 0),
246 HDD5GHZCHAN(5910, 182, 0),
247 HDD5GHZCHAN(5915, 183, 0),
248 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800249};
250
251static struct ieee80211_rate g_mode_rates[] = {
252 HDD_G_MODE_RATETAB(10, 0x1, 0),
253 HDD_G_MODE_RATETAB(20, 0x2, 0),
254 HDD_G_MODE_RATETAB(55, 0x4, 0),
255 HDD_G_MODE_RATETAB(110, 0x8, 0),
256 HDD_G_MODE_RATETAB(60, 0x10, 0),
257 HDD_G_MODE_RATETAB(90, 0x20, 0),
258 HDD_G_MODE_RATETAB(120, 0x40, 0),
259 HDD_G_MODE_RATETAB(180, 0x80, 0),
260 HDD_G_MODE_RATETAB(240, 0x100, 0),
261 HDD_G_MODE_RATETAB(360, 0x200, 0),
262 HDD_G_MODE_RATETAB(480, 0x400, 0),
263 HDD_G_MODE_RATETAB(540, 0x800, 0),
264};
265
266static struct ieee80211_rate a_mode_rates[] = {
267 HDD_G_MODE_RATETAB(60, 0x10, 0),
268 HDD_G_MODE_RATETAB(90, 0x20, 0),
269 HDD_G_MODE_RATETAB(120, 0x40, 0),
270 HDD_G_MODE_RATETAB(180, 0x80, 0),
271 HDD_G_MODE_RATETAB(240, 0x100, 0),
272 HDD_G_MODE_RATETAB(360, 0x200, 0),
273 HDD_G_MODE_RATETAB(480, 0x400, 0),
274 HDD_G_MODE_RATETAB(540, 0x800, 0),
275};
276
277static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530278 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700280 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281 .bitrates = g_mode_rates,
282 .n_bitrates = g_mode_rates_size,
283 .ht_cap.ht_supported = 1,
284 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
285 | IEEE80211_HT_CAP_GRN_FLD
286 | IEEE80211_HT_CAP_DSSSCCK40
287 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
288 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
289 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
290 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
291 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
292 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
293 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
294};
295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530297 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800298 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700299 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800300 .bitrates = a_mode_rates,
301 .n_bitrates = a_mode_rates_size,
302 .ht_cap.ht_supported = 1,
303 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
304 | IEEE80211_HT_CAP_GRN_FLD
305 | IEEE80211_HT_CAP_DSSSCCK40
306 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
307 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
308 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
309 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
310 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
311 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
312 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
313 .vht_cap.vht_supported = 1,
314};
315
316/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800317 * TX/RX direction for each kind of interface
318 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319static const struct ieee80211_txrx_stypes
320 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
321 [NL80211_IFTYPE_STATION] = {
322 .tx = 0xffff,
323 .rx = BIT(SIR_MAC_MGMT_ACTION) |
324 BIT(SIR_MAC_MGMT_PROBE_REQ),
325 },
326 [NL80211_IFTYPE_AP] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
336 [NL80211_IFTYPE_ADHOC] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
339 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
340 BIT(SIR_MAC_MGMT_PROBE_REQ) |
341 BIT(SIR_MAC_MGMT_DISASSOC) |
342 BIT(SIR_MAC_MGMT_AUTH) |
343 BIT(SIR_MAC_MGMT_DEAUTH) |
344 BIT(SIR_MAC_MGMT_ACTION),
345 },
346 [NL80211_IFTYPE_P2P_CLIENT] = {
347 .tx = 0xffff,
348 .rx = BIT(SIR_MAC_MGMT_ACTION) |
349 BIT(SIR_MAC_MGMT_PROBE_REQ),
350 },
351 [NL80211_IFTYPE_P2P_GO] = {
352 /* This is also same as for SoftAP */
353 .tx = 0xffff,
354 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
355 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
356 BIT(SIR_MAC_MGMT_PROBE_REQ) |
357 BIT(SIR_MAC_MGMT_DISASSOC) |
358 BIT(SIR_MAC_MGMT_AUTH) |
359 BIT(SIR_MAC_MGMT_DEAUTH) |
360 BIT(SIR_MAC_MGMT_ACTION),
361 },
362};
363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800364/* Interface limits and combinations registered by the driver */
365
366/* STA ( + STA ) combination */
367static const struct ieee80211_iface_limit
368 wlan_hdd_sta_iface_limit[] = {
369 {
370 .max = 3, /* p2p0 is a STA as well */
371 .types = BIT(NL80211_IFTYPE_STATION),
372 },
373};
374
375/* ADHOC (IBSS) limit */
376static const struct ieee80211_iface_limit
377 wlan_hdd_adhoc_iface_limit[] = {
378 {
379 .max = 1,
380 .types = BIT(NL80211_IFTYPE_STATION),
381 },
382 {
383 .max = 1,
384 .types = BIT(NL80211_IFTYPE_ADHOC),
385 },
386};
387
388/* AP ( + AP ) combination */
389static const struct ieee80211_iface_limit
390 wlan_hdd_ap_iface_limit[] = {
391 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530392 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 .types = BIT(NL80211_IFTYPE_AP),
394 },
395};
396
397/* P2P limit */
398static const struct ieee80211_iface_limit
399 wlan_hdd_p2p_iface_limit[] = {
400 {
401 .max = 1,
402 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
403 },
404 {
405 .max = 1,
406 .types = BIT(NL80211_IFTYPE_P2P_GO),
407 },
408};
409
410static const struct ieee80211_iface_limit
411 wlan_hdd_sta_ap_iface_limit[] = {
412 {
413 /* We need 1 extra STA interface for OBSS scan when SAP starts
414 * with HT40 in STA+SAP concurrency mode
415 */
416 .max = (1 + SAP_MAX_OBSS_STA_CNT),
417 .types = BIT(NL80211_IFTYPE_STATION),
418 },
419 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530420 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 .types = BIT(NL80211_IFTYPE_AP),
422 },
423};
424
425/* STA + P2P combination */
426static const struct ieee80211_iface_limit
427 wlan_hdd_sta_p2p_iface_limit[] = {
428 {
429 /* One reserved for dedicated P2PDEV usage */
430 .max = 2,
431 .types = BIT(NL80211_IFTYPE_STATION)
432 },
433 {
434 /* Support for two identical (GO + GO or CLI + CLI)
435 * or dissimilar (GO + CLI) P2P interfaces
436 */
437 .max = 2,
438 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
439 },
440};
441
442/* STA + AP + P2PGO combination */
443static const struct ieee80211_iface_limit
444wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
445 /* Support for AP+P2PGO interfaces */
446 {
447 .max = 2,
448 .types = BIT(NL80211_IFTYPE_STATION)
449 },
450 {
451 .max = 1,
452 .types = BIT(NL80211_IFTYPE_P2P_GO)
453 },
454 {
455 .max = 1,
456 .types = BIT(NL80211_IFTYPE_AP)
457 }
458};
459
460/* SAP + P2P combination */
461static const struct ieee80211_iface_limit
462wlan_hdd_sap_p2p_iface_limit[] = {
463 {
464 /* 1 dedicated for p2p0 which is a STA type */
465 .max = 1,
466 .types = BIT(NL80211_IFTYPE_STATION)
467 },
468 {
469 /* The p2p interface in SAP+P2P can be GO/CLI.
470 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
471 */
472 .max = 1,
473 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
474 },
475 {
476 /* SAP+GO to support only one SAP interface */
477 .max = 1,
478 .types = BIT(NL80211_IFTYPE_AP)
479 }
480};
481
482/* P2P + P2P combination */
483static const struct ieee80211_iface_limit
484wlan_hdd_p2p_p2p_iface_limit[] = {
485 {
486 /* 1 dedicated for p2p0 which is a STA type */
487 .max = 1,
488 .types = BIT(NL80211_IFTYPE_STATION)
489 },
490 {
491 /* The p2p interface in P2P+P2P can be GO/CLI.
492 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
493 */
494 .max = 2,
495 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
496 },
497};
498
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700499static const struct ieee80211_iface_limit
500 wlan_hdd_mon_iface_limit[] = {
501 {
502 .max = 3, /* Monitor interface */
503 .types = BIT(NL80211_IFTYPE_MONITOR),
504 },
505};
506
507static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 wlan_hdd_iface_combination[] = {
509 /* STA */
510 {
511 .limits = wlan_hdd_sta_iface_limit,
512 .num_different_channels = 2,
513 .max_interfaces = 3,
514 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
515 },
516 /* ADHOC */
517 {
518 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700519 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 .max_interfaces = 2,
521 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
522 },
523 /* AP */
524 {
525 .limits = wlan_hdd_ap_iface_limit,
526 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530527 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
529 },
530 /* P2P */
531 {
532 .limits = wlan_hdd_p2p_iface_limit,
533 .num_different_channels = 2,
534 .max_interfaces = 2,
535 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
536 },
537 /* STA + AP */
538 {
539 .limits = wlan_hdd_sta_ap_iface_limit,
540 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530541 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
543 .beacon_int_infra_match = true,
544 },
545 /* STA + P2P */
546 {
547 .limits = wlan_hdd_sta_p2p_iface_limit,
548 .num_different_channels = 2,
549 /* one interface reserved for P2PDEV dedicated usage */
550 .max_interfaces = 4,
551 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
552 .beacon_int_infra_match = true,
553 },
554 /* STA + P2P GO + SAP */
555 {
556 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
557 /* we can allow 3 channels for three different persona
558 * but due to firmware limitation, allow max 2 concrnt channels.
559 */
560 .num_different_channels = 2,
561 /* one interface reserved for P2PDEV dedicated usage */
562 .max_interfaces = 4,
563 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
564 .beacon_int_infra_match = true,
565 },
566 /* SAP + P2P */
567 {
568 .limits = wlan_hdd_sap_p2p_iface_limit,
569 .num_different_channels = 2,
570 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
571 .max_interfaces = 3,
572 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
573 .beacon_int_infra_match = true,
574 },
575 /* P2P + P2P */
576 {
577 .limits = wlan_hdd_p2p_p2p_iface_limit,
578 .num_different_channels = 2,
579 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
580 .max_interfaces = 3,
581 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
582 .beacon_int_infra_match = true,
583 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530584 /* Monitor */
585 {
586 .limits = wlan_hdd_mon_iface_limit,
587 .max_interfaces = 3,
588 .num_different_channels = 2,
589 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
590 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592
593static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594
595#ifdef WLAN_NL80211_TESTMODE
596enum wlan_hdd_tm_attr {
597 WLAN_HDD_TM_ATTR_INVALID = 0,
598 WLAN_HDD_TM_ATTR_CMD = 1,
599 WLAN_HDD_TM_ATTR_DATA = 2,
600 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
601 WLAN_HDD_TM_ATTR_TYPE = 4,
602 /* keep last */
603 WLAN_HDD_TM_ATTR_AFTER_LAST,
604 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
605};
606
607enum wlan_hdd_tm_cmd {
608 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
609 WLAN_HDD_TM_CMD_WLAN_HB = 1,
610};
611
612#define WLAN_HDD_TM_DATA_MAX_LEN 5000
613
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530614enum wlan_hdd_vendor_ie_access_policy {
615 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
616 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
617};
618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800619static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
620 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
621 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
622 .len = WLAN_HDD_TM_DATA_MAX_LEN},
623};
624#endif /* WLAN_NL80211_TESTMODE */
625
626#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
627static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
628 .flags = WIPHY_WOWLAN_MAGIC_PKT,
629 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
630 .pattern_min_len = 1,
631 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
632};
633#endif
634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530636 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
637 * @flags: Pointer to the flags to Add channel switch flag.
638 *
639 * This Function adds Channel Switch support flag, if channel switch is
640 * supported by kernel.
641 * Return: void.
642 */
643#ifdef CHANNEL_SWITCH_SUPPORTED
644static inline void hdd_add_channel_switch_support(uint32_t *flags)
645{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800646 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530647 return;
648}
649#else
650static inline void hdd_add_channel_switch_support(uint32_t *flags)
651{
652 return;
653}
654#endif
655
Manikandan Mohan22b83722015-12-15 15:03:23 -0800656#ifdef FEATURE_WLAN_TDLS
657
658/* TDLS capabilities params */
659#define PARAM_MAX_TDLS_SESSION \
660 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
661#define PARAM_TDLS_FEATURE_SUPPORT \
662 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
663
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530664/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
666 * @wiphy: WIPHY structure pointer
667 * @wdev: Wireless device structure pointer
668 * @data: Pointer to the data received
669 * @data_len: Length of the data received
670 *
671 * This function provides TDLS capabilities
672 *
673 * Return: 0 on success and errno on failure
674 */
675static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
676 struct wireless_dev *wdev,
677 const void *data,
678 int data_len)
679{
680 int status;
681 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
682 struct sk_buff *skb;
683 uint32_t set = 0;
684
Jeff Johnson1f61b612016-02-12 16:28:33 -0800685 ENTER_DEV(wdev->netdev);
686
Anurag Chouhan6d760662016-02-20 16:05:43 +0530687 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 hdd_err("Command not allowed in FTM mode");
689 return -EPERM;
690 }
691
692 status = wlan_hdd_validate_context(hdd_ctx);
693 if (status)
694 return status;
695
696 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
697 NLMSG_HDRLEN);
698 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700699 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 goto fail;
701 }
702
703 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800704 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
706 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 goto fail;
709 }
710 } else {
711 set = set | WIFI_TDLS_SUPPORT;
712 set = set | (hdd_ctx->config->fTDLSExternalControl ?
713 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
714 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
715 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800716 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
718 hdd_ctx->max_num_tdls_sta) ||
719 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
720 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700721 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 goto fail;
723 }
724 }
725 return cfg80211_vendor_cmd_reply(skb);
726fail:
727 if (skb)
728 kfree_skb(skb);
729 return -EINVAL;
730}
731
732/**
733 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
734 * @wiphy: WIPHY structure pointer
735 * @wdev: Wireless device structure pointer
736 * @data: Pointer to the data received
737 * @data_len: Length of the data received
738 *
739 * This function provides TDLS capabilities
740 *
741 * Return: 0 on success and errno on failure
742 */
743static int
744wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
745 struct wireless_dev *wdev,
746 const void *data,
747 int data_len)
748{
749 int ret;
750
751 cds_ssr_protect(__func__);
752 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
753 data, data_len);
754 cds_ssr_unprotect(__func__);
755
756 return ret;
757}
758#endif
759
760#ifdef QCA_HT_2040_COEX
761static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
762#endif
763
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530764int wlan_hdd_merge_avoid_freqs(tHddAvoidFreqList *destFreqList,
765 tHddAvoidFreqList *srcFreqList)
766{
767 int i;
768 tHddAvoidFreqRange *avoidRange =
769 &destFreqList->avoidFreqRange[destFreqList->avoidFreqRangeCount];
770
771 destFreqList->avoidFreqRangeCount += srcFreqList->avoidFreqRangeCount;
772 if (destFreqList->avoidFreqRangeCount > HDD_MAX_AVOID_FREQ_RANGES) {
773 hdd_err("avoid freq overflow");
774 return -EINVAL;
775 }
776
777 for (i = 0; i < srcFreqList->avoidFreqRangeCount; i++) {
778 avoidRange->startFreq =
779 srcFreqList->avoidFreqRange[i].startFreq;
780 avoidRange->endFreq = srcFreqList->avoidFreqRange[i].endFreq;
781 avoidRange++;
782 }
783 return 0;
784}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785/*
786 * FUNCTION: wlan_hdd_send_avoid_freq_event
787 * This is called when wlan driver needs to send vendor specific
788 * avoid frequency range event to userspace
789 */
790int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
791 tHddAvoidFreqList *pAvoidFreqList)
792{
793 struct sk_buff *vendor_event;
794
795 ENTER();
796
797 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700798 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 return -EINVAL;
800 }
801
802 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700803 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 return -EINVAL;
805 }
806
807 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
808 NULL,
809 sizeof(tHddAvoidFreqList),
810 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
811 GFP_KERNEL);
812 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700813 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 return -EINVAL;
815 }
816
817 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
818 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
819
820 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
821
822 EXIT();
823 return 0;
824}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530826/**
827 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
828 * with respect to the channel passed.
829 * @chan: Channel
830 * @upper: If "true" then next channel is returned or else
831 * previous channel is returned.
832 *
833 * This function returns the next/previous adjacent-channel to
834 * the channel passed. If "upper = true" then next channel is
835 * returned else previous is returned.
836 */
837int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
838{
839 enum channel_enum ch_idx = reg_get_chan_enum(chan);
840
841 if (ch_idx == INVALID_CHANNEL)
842 return -EINVAL;
843
844 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
845 ch_idx++;
846 else if (!upper && (ch_idx > CHAN_ENUM_1))
847 ch_idx--;
848 else
849 return -EINVAL;
850
851 return WLAN_REG_CH_NUM(ch_idx);
852}
853
854/**
855 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
856 * avoided when Do_Not_Break_Stream is active.
857 * @pHddCtx: HDD Context
858 * @op_chan: AP/P2P-GO operating channel
859 *
860 * This function sends list of frequencies to be avoided when
861 * Do_Not_Break_Stream is active.
862 * To clear the avoid_frequency_list in the application,
863 * op_chan = 0 can be passed.
864 *
865 * Return: 0 on success and errno on failure
866 */
867int wlan_hdd_send_avoid_freq_for_dnbs(hdd_context_t *pHddCtx, uint8_t op_chan)
868{
869 tHddAvoidFreqList p2p_avoid_freq_list;
870 uint8_t min_chan, max_chan;
871 int ret;
872 int chan;
873
874 ENTER();
875
876 if (!pHddCtx) {
877 hdd_err("invalid param");
878 return -EINVAL;
879 }
880
881 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(tHddAvoidFreqList));
882 /*
883 * If channel passed is zero, clear the avoid_freq list in application.
884 */
885 if (!op_chan) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530886#ifdef FEATURE_WLAN_CH_AVOID
887 mutex_lock(&pHddCtx->avoid_freq_lock);
888 qdf_mem_zero(&pHddCtx->dnbs_avoid_freq_list,
889 sizeof(tHddAvoidFreqList));
890 if (pHddCtx->coex_avoid_freq_list.avoidFreqRangeCount)
891 memcpy(&p2p_avoid_freq_list,
892 &pHddCtx->coex_avoid_freq_list,
893 sizeof(tHddAvoidFreqList));
894 mutex_unlock(&pHddCtx->avoid_freq_lock);
895#endif
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530896 ret = wlan_hdd_send_avoid_freq_event(pHddCtx,
897 &p2p_avoid_freq_list);
898 if (ret)
899 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
900 ret);
901
902 return ret;
903 }
904
905 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
906 min_chan = REG_MIN_24GHZ_CH_NUM;
907 max_chan = REG_MAX_24GHZ_CH_NUM;
908 } else if WLAN_REG_IS_5GHZ_CH(op_chan) {
909 min_chan = REG_MIN_5GHZ_CH_NUM;
910 max_chan = REG_MAX_5GHZ_CH_NUM;
911 } else {
912 hdd_err("invalid channel:%d", op_chan);
913 return -EINVAL;
914 }
915
916 if ((op_chan > min_chan) && (op_chan < max_chan)) {
917 p2p_avoid_freq_list.avoidFreqRangeCount = 2;
918 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
919 wlan_chan_to_freq(min_chan);
920
921 /* Get channel before the op_chan */
922 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
923 if (chan < 0)
924 return -EINVAL;
925 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
926 wlan_chan_to_freq(chan);
927
928 /* Get channel next to the op_chan */
929 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
930 if (chan < 0)
931 return -EINVAL;
932 p2p_avoid_freq_list.avoidFreqRange[1].startFreq =
933 wlan_chan_to_freq(chan);
934
935 p2p_avoid_freq_list.avoidFreqRange[1].endFreq =
936 wlan_chan_to_freq(max_chan);
937 } else if (op_chan == min_chan) {
938 p2p_avoid_freq_list.avoidFreqRangeCount = 1;
939
940 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
941 if (chan < 0)
942 return -EINVAL;
943 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
944 wlan_chan_to_freq(chan);
945
946 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
947 wlan_chan_to_freq(max_chan);
948 } else {
949 p2p_avoid_freq_list.avoidFreqRangeCount = 1;
950 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
951 wlan_chan_to_freq(min_chan);
952
953 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
954 if (chan < 0)
955 return -EINVAL;
956 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
957 wlan_chan_to_freq(chan);
958 }
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530959#ifdef FEATURE_WLAN_CH_AVOID
960 mutex_lock(&pHddCtx->avoid_freq_lock);
961 pHddCtx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
962 if (pHddCtx->coex_avoid_freq_list.avoidFreqRangeCount) {
963 ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
964 &pHddCtx->coex_avoid_freq_list);
965 if (ret) {
966 mutex_unlock(&pHddCtx->avoid_freq_lock);
967 hdd_err("avoid freq merge failed");
968 return ret;
969 }
970 }
971 mutex_unlock(&pHddCtx->avoid_freq_lock);
972#endif
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530973 ret = wlan_hdd_send_avoid_freq_event(pHddCtx, &p2p_avoid_freq_list);
974 if (ret)
975 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
976
977 return ret;
978}
979
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800980/* vendor specific events */
981static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
987 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988
989#ifdef WLAN_FEATURE_NAN
990 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
991 .vendor_id =
992 QCA_NL80211_VENDOR_ID,
993 .subcmd =
994 QCA_NL80211_VENDOR_SUBCMD_NAN
995 },
996#endif
997
998#ifdef WLAN_FEATURE_STATS_EXT
999 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1000 .vendor_id =
1001 QCA_NL80211_VENDOR_ID,
1002 .subcmd =
1003 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1004 },
1005#endif /* WLAN_FEATURE_STATS_EXT */
1006#ifdef FEATURE_WLAN_EXTSCAN
1007 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1020 .
1021 vendor_id
1022 =
1023 QCA_NL80211_VENDOR_ID,
1024 .subcmd =
1025 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1026 },
1027 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1028 .
1029 vendor_id
1030 =
1031 QCA_NL80211_VENDOR_ID,
1032 .
1033 subcmd =
1034 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1037 .
1038 vendor_id
1039 =
1040 QCA_NL80211_VENDOR_ID,
1041 .
1042 subcmd
1043 =
1044 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1045 },
1046 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1047 .
1048 vendor_id
1049 =
1050 QCA_NL80211_VENDOR_ID,
1051 .subcmd =
1052 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1053 },
1054 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1055 .vendor_id =
1056 QCA_NL80211_VENDOR_ID,
1057 .subcmd =
1058 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1059 },
1060 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1061 .
1062 vendor_id
1063 =
1064 QCA_NL80211_VENDOR_ID,
1065 .subcmd =
1066 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1067 },
1068 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1069 .
1070 vendor_id
1071 =
1072 QCA_NL80211_VENDOR_ID,
1073 .subcmd =
1074 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1075 },
1076 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1077 .
1078 vendor_id
1079 =
1080 QCA_NL80211_VENDOR_ID,
1081 .
1082 subcmd
1083 =
1084 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1085 },
1086 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1087 .
1088 vendor_id
1089 =
1090 QCA_NL80211_VENDOR_ID,
1091 .
1092 subcmd =
1093 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1094 },
1095 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1096 .
1097 vendor_id
1098 =
1099 QCA_NL80211_VENDOR_ID,
1100 .
1101 subcmd
1102 =
1103 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1104 },
1105 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1106 .
1107 vendor_id
1108 =
1109 QCA_NL80211_VENDOR_ID,
1110 .
1111 subcmd
1112 =
1113 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1114 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001115#endif /* FEATURE_WLAN_EXTSCAN */
1116
1117#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1118 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1119 .vendor_id =
1120 QCA_NL80211_VENDOR_ID,
1121 .subcmd =
1122 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1123 },
1124 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1125 .vendor_id =
1126 QCA_NL80211_VENDOR_ID,
1127 .subcmd =
1128 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1129 },
1130 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1131 .vendor_id =
1132 QCA_NL80211_VENDOR_ID,
1133 .subcmd =
1134 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1135 },
1136 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1137 .vendor_id =
1138 QCA_NL80211_VENDOR_ID,
1139 .subcmd =
1140 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1141 },
1142 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1143 .vendor_id =
1144 QCA_NL80211_VENDOR_ID,
1145 .subcmd =
1146 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1147 },
1148 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1149 .vendor_id =
1150 QCA_NL80211_VENDOR_ID,
1151 .subcmd =
1152 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1153 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001154 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1155 .vendor_id =
1156 QCA_NL80211_VENDOR_ID,
1157 .subcmd =
1158 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1159 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1161 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1162 .vendor_id =
1163 QCA_NL80211_VENDOR_ID,
1164 .subcmd =
1165 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1166 },
1167 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1168 .vendor_id = QCA_NL80211_VENDOR_ID,
1169 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1170 },
1171#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1172 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1173 .vendor_id =
1174 QCA_NL80211_VENDOR_ID,
1175 .subcmd =
1176 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1177 },
1178#endif
1179 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1180 .vendor_id =
1181 QCA_NL80211_VENDOR_ID,
1182 .subcmd =
1183 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1184 },
1185 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1186 .vendor_id =
1187 QCA_NL80211_VENDOR_ID,
1188 .subcmd =
1189 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1190 },
1191 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1192 .vendor_id =
1193 QCA_NL80211_VENDOR_ID,
1194 .subcmd =
1195 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1196 },
1197 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1198 .vendor_id =
1199 QCA_NL80211_VENDOR_ID,
1200 .subcmd =
1201 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1202 },
1203 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1204 .vendor_id =
1205 QCA_NL80211_VENDOR_ID,
1206 .subcmd =
1207 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1208 },
1209#ifdef FEATURE_WLAN_EXTSCAN
1210 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1211 .vendor_id = QCA_NL80211_VENDOR_ID,
1212 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1213 },
1214 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1215 .vendor_id = QCA_NL80211_VENDOR_ID,
1216 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1217 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1219 .vendor_id = QCA_NL80211_VENDOR_ID,
1220 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1221 },
1222#endif /* FEATURE_WLAN_EXTSCAN */
1223 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1224 .vendor_id = QCA_NL80211_VENDOR_ID,
1225 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1226 },
1227#ifdef WLAN_FEATURE_MEMDUMP
1228 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1229 .vendor_id = QCA_NL80211_VENDOR_ID,
1230 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1231 },
1232#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001233#ifdef WLAN_FEATURE_TSF
1234 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1235 .vendor_id = QCA_NL80211_VENDOR_ID,
1236 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1237 },
1238#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1240 .vendor_id = QCA_NL80211_VENDOR_ID,
1241 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1242 },
1243 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1244 .vendor_id = QCA_NL80211_VENDOR_ID,
1245 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1246 },
1247 /* OCB events */
1248 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1249 .vendor_id = QCA_NL80211_VENDOR_ID,
1250 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1251 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001252#ifdef FEATURE_LFR_SUBNET_DETECTION
1253 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1254 .vendor_id = QCA_NL80211_VENDOR_ID,
1255 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1256 },
1257#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001258
1259#ifdef WLAN_FEATURE_NAN_DATAPATH
1260 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1261 .vendor_id = QCA_NL80211_VENDOR_ID,
1262 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1263 },
1264#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001265
1266 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1267 .vendor_id = QCA_NL80211_VENDOR_ID,
1268 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1269 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301270 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1271 .vendor_id = QCA_NL80211_VENDOR_ID,
1272 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1273 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301274 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1275 .vendor_id = QCA_NL80211_VENDOR_ID,
1276 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1277 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001278#ifdef WLAN_UMAC_CONVERGENCE
1279 COMMON_VENDOR_EVENTS
1280#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001281};
1282
1283/**
1284 * __is_driver_dfs_capable() - get driver DFS capability
1285 * @wiphy: pointer to wireless wiphy structure.
1286 * @wdev: pointer to wireless_dev structure.
1287 * @data: Pointer to the data to be passed via vendor interface
1288 * @data_len:Length of the data to be passed
1289 *
1290 * This function is called by userspace to indicate whether or not
1291 * the driver supports DFS offload.
1292 *
1293 * Return: 0 on success, negative errno on failure
1294 */
1295static int __is_driver_dfs_capable(struct wiphy *wiphy,
1296 struct wireless_dev *wdev,
1297 const void *data,
1298 int data_len)
1299{
1300 u32 dfs_capability = 0;
1301 struct sk_buff *temp_skbuff;
1302 int ret_val;
1303 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1304
Jeff Johnson1f61b612016-02-12 16:28:33 -08001305 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001306
1307 ret_val = wlan_hdd_validate_context(hdd_ctx);
1308 if (ret_val)
1309 return ret_val;
1310
Anurag Chouhan6d760662016-02-20 16:05:43 +05301311 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001312 hdd_err("Command not allowed in FTM mode");
1313 return -EPERM;
1314 }
1315
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001316 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001317
1318 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1319 NLMSG_HDRLEN);
1320
1321 if (temp_skbuff != NULL) {
1322 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1323 dfs_capability);
1324 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001325 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 kfree_skb(temp_skbuff);
1327
1328 return ret_val;
1329 }
1330
1331 return cfg80211_vendor_cmd_reply(temp_skbuff);
1332 }
1333
Jeff Johnson020db452016-06-29 14:37:26 -07001334 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001335 return -ENOMEM;
1336}
1337
1338/**
1339 * is_driver_dfs_capable() - get driver DFS capability
1340 * @wiphy: pointer to wireless wiphy structure.
1341 * @wdev: pointer to wireless_dev structure.
1342 * @data: Pointer to the data to be passed via vendor interface
1343 * @data_len:Length of the data to be passed
1344 *
1345 * This function is called by userspace to indicate whether or not
1346 * the driver supports DFS offload. This is an SSR-protected
1347 * wrapper function.
1348 *
1349 * Return: 0 on success, negative errno on failure
1350 */
1351static int is_driver_dfs_capable(struct wiphy *wiphy,
1352 struct wireless_dev *wdev,
1353 const void *data,
1354 int data_len)
1355{
1356 int ret;
1357
1358 cds_ssr_protect(__func__);
1359 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1360 cds_ssr_unprotect(__func__);
1361
1362 return ret;
1363}
1364
1365/**
1366 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1367 *
1368 * @adapter: SAP adapter pointer
1369 *
1370 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1371 * radio. So in case of DFS MCC scenario override current SAP given config
1372 * to follow concurrent SAP DFS config
1373 *
1374 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1375 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1377{
1378 hdd_adapter_t *con_sap_adapter;
1379 tsap_Config_t *sap_config, *con_sap_config;
1380 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001381 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001383 if (!hdd_ctx) {
1384 hdd_err("hdd context is NULL");
1385 return 0;
1386 }
1387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 /*
1389 * Check if AP+AP case, once primary AP chooses a DFS
1390 * channel secondary AP should always follow primary APs channel
1391 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001392 if (!policy_mgr_concurrent_beaconing_sessions_running(
1393 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 return 0;
1395
1396 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1397 if (!con_sap_adapter)
1398 return 0;
1399
1400 sap_config = &adapter->sessionCtx.ap.sapConfig;
1401 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1402 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1403
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001404 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001405 return 0;
1406
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001407 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001408 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001409 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001410 sap_config->channel = con_ch;
1411
1412 if (con_sap_config->acs_cfg.acs_mode == true) {
1413 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1414 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001415 hdd_err("Primary AP channel config error");
1416 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417 con_ch, con_sap_config->acs_cfg.pri_ch,
1418 con_sap_config->acs_cfg.ht_sec_ch);
1419 return -EINVAL;
1420 }
1421 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1422 * MCC restriction. So free ch list allocated in do_acs
1423 * func for Sec AP and realloc for Pri AP ch list size
1424 */
1425 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301426 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001427
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301428 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001429 &con_sap_config->acs_cfg,
1430 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301431 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001432 sizeof(uint8_t) *
1433 con_sap_config->acs_cfg.ch_list_count);
1434 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001435 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001436 return -ENOMEM;
1437 }
1438
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301439 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440 con_sap_config->acs_cfg.ch_list,
1441 con_sap_config->acs_cfg.ch_list_count);
1442
1443 } else {
1444 sap_config->acs_cfg.pri_ch = con_ch;
1445 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1446 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1447 }
1448
1449 return con_ch;
1450}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001451
1452/**
1453 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1454 * @sap_cfg: pointer to SAP config struct
1455 *
1456 * This function sets the default ACS start and end channel for the given band
1457 * and also parses the given ACS channel list.
1458 *
1459 * Return: None
1460 */
1461
1462static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1463 bool vht_enabled)
1464{
1465 int i;
1466 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1467 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001468 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1469 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1471 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001472 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1473 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001474 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1475 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001476 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1477 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001478 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1479 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001480 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1481 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001482 }
1483
1484 if (ht_enabled)
1485 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1486
1487 if (vht_enabled)
1488 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1489
1490
1491 /* Parse ACS Chan list from hostapd */
1492 if (!sap_cfg->acs_cfg.ch_list)
1493 return;
1494
1495 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1496 sap_cfg->acs_cfg.end_ch =
1497 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1498 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301499 /* avoid channel as start channel */
1500 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1501 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1503 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1504 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1505 }
1506}
1507
1508
1509static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1510
1511/**
1512 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1513 * @adapter: pointer to SAP adapter struct
1514 *
1515 * This function starts the ACS procedure if there are no
1516 * constraints like MBSSID DFS restrictions.
1517 *
1518 * Return: Status of ACS Start procedure
1519 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301520int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001521{
1522
1523 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1524 tsap_Config_t *sap_config;
1525 tpWLAN_SAPEventCB acs_event_callback;
1526 int status;
1527
1528 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301529 if (hdd_ctx->acs_policy.acs_channel)
1530 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1531 else
1532 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533
1534 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001535 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001536 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001537
1538 if (status > 0) {
1539 /*notify hostapd about channel override */
1540 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1541 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1542 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001543 }
Jeff Johnson68755312017-02-10 11:46:55 -08001544
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1546 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001547 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001548 return -EINVAL;
1549 }
1550
1551 acs_event_callback = hdd_hostapd_sap_event_cb;
1552
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301553 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301554 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301555 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001557 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 acs_event_callback, sap_config, adapter->dev);
1559
1560
1561 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001562 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 return -EINVAL;
1564 }
bings394afdd2017-01-09 11:22:38 +08001565 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1566 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001567 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1568
1569 return 0;
1570}
1571
1572/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301573 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1574 * @ap_adapter: AP adapter
1575 * @nol: Non-occupancy list
1576 * @nol_len: Length of NOL
1577 *
1578 * Get the NOL for SAP
1579 *
1580 * Return: Zero on success, non-zero on failure
1581 */
1582static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1583 uint32_t *nol_len)
1584{
1585 QDF_STATUS ret;
1586
1587 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1588 nol, nol_len);
1589 if (QDF_IS_STATUS_ERROR(ret))
1590 return -EINVAL;
1591
1592 return 0;
1593}
1594
1595/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301596 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1597 * @hdd_ctx: hdd context
1598 * @acs_chan_params: external acs channel params
1599 * @sap_config: SAP config
1600 *
1601 * This API provides unsorted pcl list.
1602 * this list is a subset of the valid channel list given by hostapd.
1603 * if channel is not present in pcl, weightage will be given as zero
1604 *
1605 * Return: Zero on success, non-zero on failure
1606 */
1607static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1608 struct hdd_vendor_acs_chan_params *acs_chan_params,
1609 tsap_Config_t *sap_config)
1610{
1611 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301612 /*
1613 * PCL shall contain only the preferred channels from the
1614 * application. If those channels are not present in the
1615 * driver PCL, then set the weight to zero
1616 */
1617 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1618 acs_chan_params->vendor_pcl_list[i] =
1619 sap_config->acs_cfg.ch_list[i];
1620 acs_chan_params->vendor_weight_list[i] = 0;
1621 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1622 if (sap_config->acs_cfg.ch_list[i] ==
1623 sap_config->acs_cfg.pcl_channels[j]) {
1624 acs_chan_params->vendor_weight_list[i] =
1625 sap_config->
1626 acs_cfg.pcl_channels_weight_list[j];
1627 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301628 }
1629 }
1630 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301631 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301632}
1633
1634/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301635 * hdd_update_reg_chan_info : This API contructs channel info
1636 * for all the given channel
1637 * @adapter: pointer to SAP adapter struct
1638 * @channel_count: channel count
1639 * @channel_list: channel list
1640 *
1641 * Return: Status of of channel information updation
1642 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301643static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301644 uint32_t channel_count,
1645 uint8_t *channel_list)
1646{
1647 int i;
1648 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001649 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301650 uint8_t bw_offset = 0, chan = 0;
1651 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1652 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1653
1654 /* memory allocation */
1655 sap_config->channel_info = qdf_mem_malloc(
1656 sizeof(struct hdd_channel_info) *
1657 channel_count);
1658 if (!sap_config->channel_info) {
1659 hdd_err("memory allocation failed");
1660 return -ENOMEM;
1661
1662 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301663 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301664 for (i = 0; i < channel_count; i++) {
1665 icv = &sap_config->channel_info[i];
1666 chan = channel_list[i];
1667
1668 if (chan == 0)
1669 continue;
1670
1671 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1672 bw_offset = 1 << BW_40_OFFSET_BIT;
1673 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1674 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001675 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301676 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001677 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1678 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301679
1680 /* filling demo values */
1681 icv->max_radio_power = HDD_MAX_TX_POWER;
1682 icv->min_radio_power = HDD_MIN_TX_POWER;
1683 /* not supported in current driver */
1684 icv->max_antenna_gain = 0;
1685
1686 icv->reg_class_id = wlan_hdd_find_opclass(
1687 WLAN_HDD_GET_HAL_CTX(adapter),
1688 chan, bw_offset);
1689
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001690 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301691 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001692 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1693 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301694 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1695 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1696 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001697
Kapil Gupta086c6202016-12-11 18:17:06 +05301698 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001699 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301700 sap_config->acs_cfg.ch_width,
1701 sap_config->acs_cfg.is_ht_enabled,
1702 sap_config->acs_cfg.is_vht_enabled,
1703 hdd_ctx->config->enable_sub_20_channel_width);
1704
1705 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1706 icv->freq, icv->flags,
1707 icv->flagext, icv->ieee_chan_number,
1708 icv->max_reg_power, icv->max_radio_power,
1709 icv->min_radio_power, icv->reg_class_id,
1710 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1711 icv->vht_center_freq_seg1);
1712 }
1713 return 0;
1714}
1715
1716/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1717#define CHAN_INFO_ATTR_FLAGS \
1718 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1719#define CHAN_INFO_ATTR_FLAG_EXT \
1720 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1721#define CHAN_INFO_ATTR_FREQ \
1722 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1723#define CHAN_INFO_ATTR_MAX_REG_POWER \
1724 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1725#define CHAN_INFO_ATTR_MAX_POWER \
1726 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1727#define CHAN_INFO_ATTR_MIN_POWER \
1728 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1729#define CHAN_INFO_ATTR_REG_CLASS_ID \
1730 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1731#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1732 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1733#define CHAN_INFO_ATTR_VHT_SEG_0 \
1734 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1735#define CHAN_INFO_ATTR_VHT_SEG_1 \
1736 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1737
1738/**
1739 * hdd_cfg80211_update_channel_info() - add channel info attributes
1740 * @skb: pointer to sk buff
1741 * @hdd_ctx: pointer to hdd station context
1742 * @idx: attribute index
1743 *
1744 * Return: Success(0) or reason code for failure
1745 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301746static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301747hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1748 tsap_Config_t *sap_config, int idx)
1749{
1750 struct nlattr *nla_attr, *channel;
1751 struct hdd_channel_info *icv;
1752 int i;
1753
1754 nla_attr = nla_nest_start(skb, idx);
1755 if (!nla_attr)
1756 goto fail;
1757
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301758 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301759 channel = nla_nest_start(skb, i);
1760 if (!channel)
1761 goto fail;
1762
1763 icv = &sap_config->channel_info[i];
1764 if (!icv) {
1765 hdd_err("channel info not found");
1766 goto fail;
1767 }
1768 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1769 icv->freq) ||
1770 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1771 icv->flags) ||
1772 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1773 icv->flagext) ||
1774 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1775 icv->max_reg_power) ||
1776 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1777 icv->max_radio_power) ||
1778 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1779 icv->min_radio_power) ||
1780 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1781 icv->reg_class_id) ||
1782 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1783 icv->max_antenna_gain) ||
1784 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1785 icv->vht_center_freq_seg0) ||
1786 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1787 icv->vht_center_freq_seg1)) {
1788 hdd_err("put fail");
1789 goto fail;
1790 }
1791 nla_nest_end(skb, channel);
1792 }
1793 nla_nest_end(skb, nla_attr);
1794 return 0;
1795fail:
1796 hdd_err("nl channel update failed");
1797 return -EINVAL;
1798}
1799#undef CHAN_INFO_ATTR_FLAGS
1800#undef CHAN_INFO_ATTR_FLAG_EXT
1801#undef CHAN_INFO_ATTR_FREQ
1802#undef CHAN_INFO_ATTR_MAX_REG_POWER
1803#undef CHAN_INFO_ATTR_MAX_POWER
1804#undef CHAN_INFO_ATTR_MIN_POWER
1805#undef CHAN_INFO_ATTR_REG_CLASS_ID
1806#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1807#undef CHAN_INFO_ATTR_VHT_SEG_0
1808#undef CHAN_INFO_ATTR_VHT_SEG_1
1809
1810/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301811 * hdd_cfg80211_update_pcl() - add pcl info attributes
1812 * @skb: pointer to sk buff
1813 * @hdd_ctx: pointer to hdd station context
1814 * @idx: attribute index
1815 * @vendor_pcl_list: PCL list
1816 * @vendor_weight_list: PCL weights
1817 *
1818 * Return: Success(0) or reason code for failure
1819 */
1820static int32_t
1821hdd_cfg80211_update_pcl(struct sk_buff *skb,
1822 uint8_t ch_list_count, int idx,
1823 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1824{
1825 struct nlattr *nla_attr, *channel;
1826 int i;
1827
1828 nla_attr = nla_nest_start(skb, idx);
1829
1830 if (!nla_attr)
1831 goto fail;
1832
1833 for (i = 0; i < ch_list_count; i++) {
1834 channel = nla_nest_start(skb, i);
1835 if (!channel)
1836 goto fail;
1837 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1838 vendor_pcl_list[i]) ||
1839 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1840 vendor_weight_list[i])) {
1841 hdd_err("put fail");
1842 goto fail;
1843 }
1844 nla_nest_end(skb, channel);
1845 }
1846 nla_nest_end(skb, nla_attr);
1847
1848 return 0;
1849fail:
1850 hdd_err("updating pcl list failed");
1851 return -EINVAL;
1852}
1853
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301854static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
1855 tsap_Config_t *sap_config,
1856 eCsrBand *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301857{
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301858 int i, temp_count = 0;
1859 int acs_list_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301860 /* Get scan band */
1861 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1862 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1863 *band = eCSR_BAND_24;
1864 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1865 *band = eCSR_BAND_5G;
1866 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1867 *band = eCSR_BAND_ALL;
1868 }
1869 /* Auto is not supported currently */
1870 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1871 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301872 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
1873 hdd_ctx->config->external_acs_freq_band)
1874 *band = eCSR_BAND_24;
1875 else
1876 *band = eCSR_BAND_5G;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301877 for (i = 0; i < acs_list_count; i++) {
1878 if (eCSR_BAND_24 == *band) {
1879 if (WLAN_REG_IS_24GHZ_CH(
1880 sap_config->acs_cfg.ch_list[i])) {
1881 sap_config->acs_cfg.ch_list[
1882 temp_count] =
1883 sap_config->acs_cfg.ch_list[i];
1884 temp_count++;
1885 }
1886 } else if (eCSR_BAND_5G == *band) {
1887 if (WLAN_REG_IS_5GHZ_CH(
1888 sap_config->acs_cfg.ch_list[i])) {
1889 sap_config->acs_cfg.ch_list[
1890 temp_count] =
1891 sap_config->acs_cfg.ch_list[i];
1892 temp_count++;
1893 }
1894 }
1895 }
1896 sap_config->acs_cfg.ch_list_count = temp_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301897 }
1898}
1899
1900void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1901 uint8_t reason)
1902{
1903 struct sk_buff *skb;
1904 tsap_Config_t *sap_config;
1905 uint32_t channel_count = 0, status;
1906 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1907 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1908 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1909 struct hdd_vendor_acs_chan_params acs_chan_params;
1910 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1911 eCsrBand band = eCSR_BAND_24;
1912 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301913 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
1914 uint32_t i;
1915
Kapil Gupta8878ad92017-02-13 11:56:04 +05301916
1917 if (!hdd_ctx) {
1918 hdd_err("HDD context is NULL");
1919 return;
1920 }
1921
1922 ENTER();
1923 sap_config = &adapter->sessionCtx.ap.sapConfig;
1924
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301925 hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301926 /* Get valid channels for SAP */
1927 wlan_hdd_sap_get_valid_channellist(adapter,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301928 &channel_count,
1929 channel_list,
1930 band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301931
1932 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301933 /* Get phymode */
1934 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1935
1936 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1937 &(adapter->wdev),
1938 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1939 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1940 GFP_KERNEL);
1941
1942 if (!skb) {
1943 hdd_err("cfg80211_vendor_event_alloc failed");
1944 return;
1945 }
1946 /*
1947 * Application expects pcl to be a subset of channel list
1948 * Remove all channels which are not in channel list from pcl
1949 * and add weight as zero
1950 */
1951 acs_chan_params.channel_count = channel_count;
1952 acs_chan_params.channel_list = channel_list;
1953 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1954 acs_chan_params.vendor_weight_list = vendor_weight_list;
1955
1956 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1957 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301958
1959 if (acs_chan_params.channel_count) {
1960 hdd_debug("ACS channel list: len: %d",
1961 acs_chan_params.channel_count);
1962 for (i = 0; i < acs_chan_params.channel_count; i++)
1963 hdd_debug("%d ", acs_chan_params.channel_list[i]);
1964 }
1965
1966 if (acs_chan_params.pcl_count) {
1967 hdd_debug("ACS PCL list: len: %d",
1968 acs_chan_params.pcl_count);
1969 for (i = 0; i < acs_chan_params.pcl_count; i++)
1970 hdd_debug("channel:%d, weight:%d ",
1971 acs_chan_params.
1972 vendor_pcl_list[i],
1973 acs_chan_params.
1974 vendor_weight_list[i]);
1975 }
1976
1977 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1978 hdd_ctx->config->external_acs_policy) {
1979 acs_policy =
1980 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
1981 } else {
1982 acs_policy =
1983 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
1984 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301985 /* Update values in NL buffer */
1986 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1987 reason) ||
1988 nla_put_u8(skb,
1989 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1990 false) ||
1991 nla_put_u8(skb,
1992 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1993 true) ||
1994 nla_put_u8(skb,
1995 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1996 true) ||
1997 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1998 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05301999 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
2000 band) ||
2001 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
2002 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05302003 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302004 channel_count, channel_list)) {
2005 hdd_err("nla put fail");
2006 goto fail;
2007 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302008 status =
2009 hdd_cfg80211_update_pcl(skb,
2010 acs_chan_params.
2011 pcl_count,
2012 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
2013 vendor_pcl_list,
2014 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302015
2016 if (status != 0)
2017 goto fail;
2018
2019 status = hdd_cfg80211_update_channel_info(skb, sap_config,
2020 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
2021
2022 if (status != 0)
2023 goto fail;
2024
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302025 status = nla_put_u32(skb,
2026 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
2027 acs_policy);
2028
2029 if (status != 0)
2030 goto fail;
2031
Kapil Gupta8878ad92017-02-13 11:56:04 +05302032 cfg80211_vendor_event(skb, GFP_KERNEL);
2033 return;
2034fail:
2035 if (skb)
2036 kfree_skb(skb);
2037}
2038
2039static int hdd_create_acs_timer(hdd_adapter_t *adapter)
2040{
2041 struct hdd_external_acs_timer_context *timer_context;
2042
2043 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
2044 return 0;
2045
2046 hdd_notice("Starting vendor app based ACS");
2047 timer_context = qdf_mem_malloc(sizeof(*timer_context));
2048 timer_context->adapter = adapter;
2049
2050 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
2051 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
2052 QDF_TIMER_TYPE_SW,
2053 hdd_acs_response_timeout_handler, timer_context);
2054 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
2055 return 0;
2056}
2057
2058/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002059 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2060 * @wiphy: Linux wiphy struct pointer
2061 * @wdev: Linux wireless device struct pointer
2062 * @data: ACS information from hostapd
2063 * @data_len: ACS information length
2064 *
2065 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2066 * and starts ACS procedure.
2067 *
2068 * Return: ACS procedure start status
2069 */
2070
2071static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2072 struct wireless_dev *wdev,
2073 const void *data, int data_len)
2074{
2075 struct net_device *ndev = wdev->netdev;
2076 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
2077 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2078 tsap_Config_t *sap_config;
2079 struct sk_buff *temp_skbuff;
2080 int status = -EINVAL, i = 0;
2081 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2082 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302083 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084
2085 /* ***Note*** Donot set SME config related to ACS operation here because
2086 * ACS operation is not synchronouse and ACS for Second AP may come when
2087 * ACS operation for first AP is going on. So only do_acs is split to
2088 * seperate start_acs routine. Also SME-PMAC struct that is used to
2089 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2090 * config shall be set only from start_acs.
2091 */
2092
2093 /* nla_policy Policy template. Policy not applied as some attributes are
2094 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
2095 *
2096 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2097 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2098 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2099 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2100 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2101 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
2102 */
2103
Jeff Johnson1f61b612016-02-12 16:28:33 -08002104 ENTER_DEV(ndev);
2105
Anurag Chouhan6d760662016-02-20 16:05:43 +05302106 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107 hdd_err("Command not allowed in FTM mode");
2108 return -EPERM;
2109 }
2110
Kapil Gupta8878ad92017-02-13 11:56:04 +05302111 if (hdd_ctx->config->force_sap_acs &&
2112 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07002113 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002114 return -EPERM;
2115 }
2116
2117 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302118 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302120
Naveen Rawat64e477e2016-05-20 10:34:56 -07002121 if (cds_is_sub_20_mhz_enabled()) {
2122 hdd_err("ACS not supported in sub 20 MHz ch wd.");
2123 status = -EINVAL;
2124 goto out;
2125 }
2126
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302128 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002129
2130 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
2131 NULL);
2132 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07002133 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002134 goto out;
2135 }
2136
2137 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002138 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139 goto out;
2140 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302141 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
2142 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143
2144 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2145 ht_enabled =
2146 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2147 else
2148 ht_enabled = 0;
2149
2150 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2151 ht40_enabled =
2152 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2153 else
2154 ht40_enabled = 0;
2155
2156 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2157 vht_enabled =
2158 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2159 else
2160 vht_enabled = 0;
2161
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302162 if (hdd_ctx->config->sap_force_11n_for_11ac) {
2163 vht_enabled = 0;
2164 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
2165 }
2166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002167 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2168 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2169 } else {
2170 if (ht_enabled && ht40_enabled)
2171 ch_width = 40;
2172 else
2173 ch_width = 20;
2174 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302175
2176 /* this may be possible, when sap_force_11n_for_11ac is set */
2177 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2178 if (ht_enabled && ht40_enabled)
2179 ch_width = 40;
2180 else
2181 ch_width = 20;
2182 }
2183
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 if (ch_width == 80)
2185 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2186 else if (ch_width == 40)
2187 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2188 else
2189 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2190
2191 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2192 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2193 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2194 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2195 * since it contains the frequency values of the channels in
2196 * the channel list.
2197 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2198 * is present
2199 */
2200 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2201 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2202 sap_config->acs_cfg.ch_list_count = nla_len(
2203 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2204 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302205 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002206 sizeof(uint8_t) *
2207 sap_config->acs_cfg.ch_list_count);
2208 if (sap_config->acs_cfg.ch_list == NULL)
2209 goto out;
2210
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302211 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 sap_config->acs_cfg.ch_list_count);
2213 }
2214 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2215 uint32_t *freq =
2216 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2217 sap_config->acs_cfg.ch_list_count = nla_len(
2218 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2219 sizeof(uint32_t);
2220 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302221 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002222 sap_config->acs_cfg.ch_list_count);
2223 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07002224 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225 status = -ENOMEM;
2226 goto out;
2227 }
2228
2229 /* convert frequency to channel */
2230 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2231 sap_config->acs_cfg.ch_list[i] =
2232 ieee80211_frequency_to_channel(freq[i]);
2233 }
2234 }
2235
2236 hdd_debug("get pcl for DO_ACS vendor command");
2237
2238 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002239 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302240 sap_config->acs_cfg.pcl_channels,
2241 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302242 sap_config->acs_cfg.pcl_channels_weight_list,
2243 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302244 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002245 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302247 if (sap_config->acs_cfg.pcl_ch_count) {
2248 hdd_debug("ACS config PCL: len: %d",
2249 sap_config->acs_cfg.pcl_ch_count);
2250 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2251 hdd_debug("channel:%d, weight:%d ",
2252 sap_config->acs_cfg.
2253 pcl_channels[i],
2254 sap_config->acs_cfg.
2255 pcl_channels_weight_list[i]);
2256 }
2257
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002258 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302259 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2260 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002261 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262 vht_enabled = 1;
2263 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2264 sap_config->acs_cfg.ch_width =
2265 hdd_ctx->config->vhtChannelWidth;
2266 /* No VHT80 in 2.4G so perform ACS accordingly */
2267 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302268 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302270 ch_width = 40;
2271 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 }
2273
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302274 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2275
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002276 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 -08002277 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2278 ch_width, ht_enabled, vht_enabled,
2279 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2280
Kapil Gupta8878ad92017-02-13 11:56:04 +05302281 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2282 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002284 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002285 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 sap_config->acs_cfg.ch_list_count);
2287 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002288 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002289 }
2290 sap_config->acs_cfg.acs_mode = true;
2291 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002292 /* ***Note*** Completion variable usage is not allowed
2293 * here since ACS scan operation may take max 2.2 sec
2294 * for 5G band:
2295 * 9 Active channel X 40 ms active scan time +
2296 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2298 * for this long. So we split up the scanning part.
2299 */
2300 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002301 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 status = 0;
2303 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302304 /* Check if vendor specific acs is enabled */
2305 if (hdd_ctx->config->vendor_acs_support) {
2306 sap_config->acs_cfg.hw_mode = hw_mode;
2307 hdd_create_acs_timer(adapter);
2308 hdd_update_acs_timer_reason(adapter,
2309 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2310 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2311 wlan_sap_set_vendor_acs(
2312 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2313 true);
2314 else
2315 wlan_sap_set_vendor_acs(
2316 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2317 false);
2318
2319 } else
2320 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002321 }
2322
2323out:
2324 if (0 == status) {
2325 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2326 NLMSG_HDRLEN);
2327 if (temp_skbuff != NULL)
2328 return cfg80211_vendor_cmd_reply(temp_skbuff);
2329 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002330 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002331 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2332
2333 return status;
2334}
2335
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002336/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2338 * @wiphy: Linux wiphy struct pointer
2339 * @wdev: Linux wireless device struct pointer
2340 * @data: ACS information from hostapd
2341 * @data_len: ACS information len
2342 *
2343 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2344 * and starts ACS procedure.
2345 *
2346 * Return: ACS procedure start status
2347 */
2348
2349static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2350 struct wireless_dev *wdev,
2351 const void *data, int data_len)
2352{
2353 int ret;
2354
2355 cds_ssr_protect(__func__);
2356 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2357 cds_ssr_unprotect(__func__);
2358
2359 return ret;
2360}
2361
2362/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002363 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2364 * @adapter: Pointer to adapter struct
2365 *
2366 * This function handle cleanup of what was done in DO_ACS, including free
2367 * memory.
2368 *
2369 * Return: void
2370 */
2371
2372void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2373{
2374 if (adapter == NULL)
2375 return;
2376 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2377 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2378 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2379 }
2380}
2381
2382/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2384 * @work: Linux workqueue struct pointer for ACS work
2385 *
2386 * This function starts the ACS procedure which was marked pending when an ACS
2387 * procedure was in progress for a concurrent SAP interface.
2388 *
2389 * Return: None
2390 */
2391
2392static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2393{
2394 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2395 acs_pending_work.work);
2396 wlan_hdd_cfg80211_start_acs(adapter);
2397}
2398
2399/**
2400 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2401 * @adapter: Pointer to SAP adapter struct
2402 * @pri_channel: SAP ACS procedure selected Primary channel
2403 * @sec_channel: SAP ACS procedure selected secondary channel
2404 *
2405 * This is a callback function from SAP module on ACS procedure is completed.
2406 * This function send the ACS selected channel information to hostapd
2407 *
2408 * Return: None
2409 */
2410
2411void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2412{
2413 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2414 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2415 struct sk_buff *vendor_event;
2416 int ret_val;
2417 hdd_adapter_t *con_sap_adapter;
2418 uint16_t ch_width;
2419
2420 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002421 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002422 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2423 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2424 GFP_KERNEL);
2425
2426 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002427 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 return;
2429 }
2430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431 ret_val = nla_put_u8(vendor_event,
2432 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2433 sap_cfg->acs_cfg.pri_ch);
2434 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002435 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436 kfree_skb(vendor_event);
2437 return;
2438 }
2439
2440 ret_val = nla_put_u8(vendor_event,
2441 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2442 sap_cfg->acs_cfg.ht_sec_ch);
2443 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002444 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 kfree_skb(vendor_event);
2446 return;
2447 }
2448
2449 ret_val = nla_put_u8(vendor_event,
2450 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2451 sap_cfg->acs_cfg.vht_seg0_center_ch);
2452 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002453 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 kfree_skb(vendor_event);
2455 return;
2456 }
2457
2458 ret_val = nla_put_u8(vendor_event,
2459 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2460 sap_cfg->acs_cfg.vht_seg1_center_ch);
2461 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002462 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 kfree_skb(vendor_event);
2464 return;
2465 }
2466
2467 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2468 ch_width = 80;
2469 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2470 ch_width = 40;
2471 else
2472 ch_width = 20;
2473
2474 ret_val = nla_put_u16(vendor_event,
2475 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2476 ch_width);
2477 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002478 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 kfree_skb(vendor_event);
2480 return;
2481 }
2482 if (sap_cfg->acs_cfg.pri_ch > 14)
2483 ret_val = nla_put_u8(vendor_event,
2484 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2485 QCA_ACS_MODE_IEEE80211A);
2486 else
2487 ret_val = nla_put_u8(vendor_event,
2488 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2489 QCA_ACS_MODE_IEEE80211G);
2490
2491 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002492 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002493 kfree_skb(vendor_event);
2494 return;
2495 }
2496
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002497 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 -08002498 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2499 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2500 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2501
2502 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2503 /* ***Note*** As already mentioned Completion variable usage is not
2504 * allowed here since ACS scan operation may take max 2.2 sec.
2505 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2506 * operation.
2507 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2508 * when Primary AP ACS is complete and secondary AP ACS is started here
2509 * immediately, Primary AP start_bss may come inbetween ACS operation
2510 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2511 * delay. This path and below constraint will be removed on sessionizing
2512 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2513 * As per design constraint user space control application must take
2514 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2515 * this code path. Sec AP hostapd should be started after Primary AP
2516 * start beaconing which can be confirmed by getchannel iwpriv command
2517 */
2518
2519 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2520 if (con_sap_adapter &&
2521 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2523 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 /* Lets give 500ms for OBSS + START_BSS to complete */
2525 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2526 msecs_to_jiffies(500));
2527 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2528 }
2529
2530 return;
2531}
2532
2533static int
2534__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2535 struct wireless_dev *wdev,
2536 const void *data,
2537 int data_len)
2538{
2539 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2540 struct sk_buff *skb = NULL;
2541 uint32_t fset = 0;
2542 int ret;
2543
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002544 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302545
Anurag Chouhan6d760662016-02-20 16:05:43 +05302546 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 hdd_err("Command not allowed in FTM mode");
2548 return -EPERM;
2549 }
2550
2551 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302552 if (ret)
2553 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554
2555 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002556 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 fset |= WIFI_FEATURE_INFRA;
2558 }
2559 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002560 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 fset |= WIFI_FEATURE_INFRA_5G;
2562 }
2563#ifdef WLAN_FEATURE_P2P
2564 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2565 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002566 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567 fset |= WIFI_FEATURE_P2P;
2568 }
2569#endif
2570 fset |= WIFI_FEATURE_SOFT_AP;
2571
2572 /* HOTSPOT is a supplicant feature, enable it by default */
2573 fset |= WIFI_FEATURE_HOTSPOT;
2574
2575#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302576 if (pHddCtx->config->extscan_enabled &&
2577 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002578 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2580 }
2581#endif
2582 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002583 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584 fset |= WIFI_FEATURE_NAN;
2585 }
2586 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002587 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002588 fset |= WIFI_FEATURE_D2D_RTT;
2589 fset |= WIFI_FEATURE_D2AP_RTT;
2590 }
2591#ifdef FEATURE_WLAN_SCAN_PNO
2592 if (pHddCtx->config->configPNOScanSupport &&
2593 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002594 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 fset |= WIFI_FEATURE_PNO;
2596 }
2597#endif
2598 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2599#ifdef FEATURE_WLAN_TDLS
2600 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2601 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002602 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 fset |= WIFI_FEATURE_TDLS;
2604 }
2605 if (sme_is_feature_supported_by_fw(TDLS) &&
2606 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2607 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002608 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2610 }
2611#endif
2612#ifdef WLAN_AP_STA_CONCURRENCY
2613 fset |= WIFI_FEATURE_AP_STA;
2614#endif
2615 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002616 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002617
2618 if (hdd_link_layer_stats_supported())
2619 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2620
2621 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2622 NLMSG_HDRLEN);
2623 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002624 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 return -EINVAL;
2626 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002627 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002629 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630 goto nla_put_failure;
2631 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302632 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302633 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002634nla_put_failure:
2635 kfree_skb(skb);
2636 return -EINVAL;
2637}
2638
2639/**
2640 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2641 * @wiphy: pointer to wireless wiphy structure.
2642 * @wdev: pointer to wireless_dev structure.
2643 * @data: Pointer to the data to be passed via vendor interface
2644 * @data_len:Length of the data to be passed
2645 *
2646 * Return: Return the Success or Failure code.
2647 */
2648static int
2649wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2650 struct wireless_dev *wdev,
2651 const void *data, int data_len)
2652{
2653 int ret = 0;
2654
2655 cds_ssr_protect(__func__);
2656 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2657 data, data_len);
2658 cds_ssr_unprotect(__func__);
2659
2660 return ret;
2661}
2662
2663/**
2664 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2665 * @wiphy: pointer to wireless wiphy structure.
2666 * @wdev: pointer to wireless_dev structure.
2667 * @data: Pointer to the data to be passed via vendor interface
2668 * @data_len:Length of the data to be passed
2669 *
2670 * Set the MAC address that is to be used for scanning.
2671 *
2672 * Return: Return the Success or Failure code.
2673 */
2674static int
2675__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2676 struct wireless_dev *wdev,
2677 const void *data,
2678 int data_len)
2679{
2680 tpSirScanMacOui pReqMsg = NULL;
2681 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2682 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302683 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 int ret;
2685
Jeff Johnson1f61b612016-02-12 16:28:33 -08002686 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687
Anurag Chouhan6d760662016-02-20 16:05:43 +05302688 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 hdd_err("Command not allowed in FTM mode");
2690 return -EPERM;
2691 }
2692
2693 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302694 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696
2697 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002698 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699 return -ENOTSUPP;
2700 }
2701
2702 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2703 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002704 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 return -EINVAL;
2706 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302707 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002709 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 return -ENOMEM;
2711 }
2712 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002713 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 goto fail;
2715 }
2716 nla_memcpy(&pReqMsg->oui[0],
2717 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2718 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002719 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 pReqMsg->oui[1], pReqMsg->oui[2]);
2721 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302722 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002723 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724 goto fail;
2725 }
2726 return 0;
2727fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302728 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002729 return -EINVAL;
2730}
2731
2732/**
2733 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2734 * @wiphy: pointer to wireless wiphy structure.
2735 * @wdev: pointer to wireless_dev structure.
2736 * @data: Pointer to the data to be passed via vendor interface
2737 * @data_len:Length of the data to be passed
2738 *
2739 * Set the MAC address that is to be used for scanning. This is an
2740 * SSR-protecting wrapper function.
2741 *
2742 * Return: Return the Success or Failure code.
2743 */
2744static int
2745wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2746 struct wireless_dev *wdev,
2747 const void *data,
2748 int data_len)
2749{
2750 int ret;
2751
2752 cds_ssr_protect(__func__);
2753 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2754 data, data_len);
2755 cds_ssr_unprotect(__func__);
2756
2757 return ret;
2758}
2759
2760/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302761 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2762 * @wiphy: pointer phy adapter
2763 * @wdev: pointer to wireless device structure
2764 * @data: pointer to data buffer
2765 * @data_len: length of data
2766 *
2767 * This routine will give concurrency matrix
2768 *
2769 * Return: int status code
2770 */
2771static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2772 struct wireless_dev *wdev,
2773 const void *data,
2774 int data_len)
2775{
2776 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2777 uint8_t i, feature_sets, max_feature_sets;
2778 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2779 struct sk_buff *reply_skb;
2780 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2781 int ret;
2782
2783 ENTER_DEV(wdev->netdev);
2784
2785 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2786 hdd_err("Command not allowed in FTM mode");
2787 return -EPERM;
2788 }
2789
2790 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302791 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302792 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302793
2794 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2795 data, data_len, NULL)) {
2796 hdd_err("Invalid ATTR");
2797 return -EINVAL;
2798 }
2799
2800 /* Parse and fetch max feature set */
2801 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2802 hdd_err("Attr max feature set size failed");
2803 return -EINVAL;
2804 }
2805 max_feature_sets = nla_get_u32(tb[
2806 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002807 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302808
2809 /* Fill feature combination matrix */
2810 feature_sets = 0;
2811 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002812 WIFI_FEATURE_P2P;
2813 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2814 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302815 /* Add more feature combinations here */
2816
2817 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002818 hdd_debug("Number of feature sets: %d", feature_sets);
2819 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302820 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002821 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302822
2823 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2824 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2825 if (!reply_skb) {
2826 hdd_err("Feature set matrix: buffer alloc fail");
2827 return -ENOMEM;
2828 }
2829
2830 if (nla_put_u32(reply_skb,
2831 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2832 feature_sets) ||
2833 nla_put(reply_skb,
2834 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2835 sizeof(u32) * feature_sets,
2836 feature_set_matrix)) {
2837 hdd_err("nla put fail");
2838 kfree_skb(reply_skb);
2839 return -EINVAL;
2840 }
2841 return cfg80211_vendor_cmd_reply(reply_skb);
2842}
2843
2844/**
2845 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2846 * @wiphy: pointer to wireless wiphy structure.
2847 * @wdev: pointer to wireless_dev structure.
2848 * @data: Pointer to the data to be passed via vendor interface
2849 * @data_len:Length of the data to be passed
2850 *
2851 * Retrieves the concurrency feature set matrix
2852 *
2853 * Return: 0 on success, negative errno on failure
2854 */
2855static int
2856wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2857 struct wireless_dev *wdev,
2858 const void *data,
2859 int data_len)
2860{
2861 int ret;
2862
2863 cds_ssr_protect(__func__);
2864 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2865 data, data_len);
2866 cds_ssr_unprotect(__func__);
2867
2868 return ret;
2869}
2870
2871/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002872 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2873 * @feature_flags: pointer to the byte array of features.
2874 * @feature: Feature to be turned ON in the byte array.
2875 *
2876 * Return: None
2877 *
2878 * This is called to turn ON or SET the feature flag for the requested feature.
2879 **/
2880#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002881static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2882 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883{
2884 uint32_t index;
2885 uint8_t bit_mask;
2886
2887 index = feature / NUM_BITS_IN_BYTE;
2888 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2889 feature_flags[index] |= bit_mask;
2890}
2891
2892/**
2893 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2894 * @wiphy: pointer to wireless wiphy structure.
2895 * @wdev: pointer to wireless_dev structure.
2896 * @data: Pointer to the data to be passed via vendor interface
2897 * @data_len:Length of the data to be passed
2898 *
2899 * This is called when wlan driver needs to send supported feature set to
2900 * supplicant upon a request/query from the supplicant.
2901 *
2902 * Return: Return the Success or Failure code.
2903 **/
2904#define MAX_CONCURRENT_CHAN_ON_24G 2
2905#define MAX_CONCURRENT_CHAN_ON_5G 2
2906static int
2907__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2908 struct wireless_dev *wdev,
2909 const void *data, int data_len)
2910{
2911 struct sk_buff *skb = NULL;
2912 uint32_t dbs_capability = 0;
2913 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302914 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 int ret_val;
2916
2917 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2918 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2919
Jeff Johnson1f61b612016-02-12 16:28:33 -08002920 ENTER_DEV(wdev->netdev);
2921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2923 if (ret_val)
2924 return ret_val;
2925
Anurag Chouhan6d760662016-02-20 16:05:43 +05302926 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927 hdd_err("Command not allowed in FTM mode");
2928 return -EPERM;
2929 }
2930
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002931 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002932 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002933 wlan_hdd_cfg80211_set_feature(feature_flags,
2934 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2935 }
2936
2937 wlan_hdd_cfg80211_set_feature(feature_flags,
2938 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002939 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 wlan_hdd_cfg80211_set_feature(feature_flags,
2941 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002942
2943 if (wma_is_p2p_lo_capable())
2944 wlan_hdd_cfg80211_set_feature(feature_flags,
2945 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2946
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2948 NLMSG_HDRLEN);
2949
2950 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002951 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 return -ENOMEM;
2953 }
2954
2955 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2956 sizeof(feature_flags), feature_flags))
2957 goto nla_put_failure;
2958
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002959 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2960 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302961 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 if (one_by_one_dbs)
2963 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2964
2965 if (two_by_two_dbs)
2966 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2967
2968 if (!one_by_one_dbs && !two_by_two_dbs)
2969 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2970 } else {
2971 hdd_err("wma_get_dbs_hw_mode failed");
2972 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2973 }
2974
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002975 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976
2977 if (nla_put_u32(skb,
2978 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2979 MAX_CONCURRENT_CHAN_ON_24G))
2980 goto nla_put_failure;
2981
2982 if (nla_put_u32(skb,
2983 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2984 MAX_CONCURRENT_CHAN_ON_5G))
2985 goto nla_put_failure;
2986
2987 return cfg80211_vendor_cmd_reply(skb);
2988
2989nla_put_failure:
2990 kfree_skb(skb);
2991 return -EINVAL;
2992}
2993
2994/**
2995 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2996 * @wiphy: pointer to wireless wiphy structure.
2997 * @wdev: pointer to wireless_dev structure.
2998 * @data: Pointer to the data to be passed via vendor interface
2999 * @data_len:Length of the data to be passed
3000 *
3001 * This is called when wlan driver needs to send supported feature set to
3002 * supplicant upon a request/query from the supplicant.
3003 *
3004 * Return: Return the Success or Failure code.
3005 */
3006static int
3007wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3008 struct wireless_dev *wdev,
3009 const void *data, int data_len)
3010{
3011 int ret;
3012
3013 cds_ssr_protect(__func__);
3014 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
3015 data, data_len);
3016 cds_ssr_unprotect(__func__);
3017
3018 return ret;
3019}
3020
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303021#define PARAM_NUM_NW \
3022 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
3023#define PARAM_SET_BSSID \
3024 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
3025#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
3026#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027
3028/**
3029 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
3030 * @wiphy: The wiphy structure
3031 * @wdev: The wireless device
3032 * @data: Data passed by framework
3033 * @data_len: Parameters to be configured passed as data
3034 *
3035 * The roaming related parameters are configured by the framework
3036 * using this interface.
3037 *
3038 * Return: Return either success or failure code.
3039 */
3040static int
3041__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3042 struct wireless_dev *wdev, const void *data, int data_len)
3043{
3044 struct net_device *dev = wdev->netdev;
3045 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3046 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3047 uint8_t session_id;
3048 struct roam_ext_params roam_params;
3049 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303050 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
3052 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
3053 int rem, i;
3054 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08003055 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 int ret;
3057
Jeff Johnson1f61b612016-02-12 16:28:33 -08003058 ENTER_DEV(dev);
3059
Anurag Chouhan6d760662016-02-20 16:05:43 +05303060 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 hdd_err("Command not allowed in FTM mode");
3062 return -EPERM;
3063 }
3064
3065 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303066 if (ret)
3067 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003068
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05303069 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
3070 hdd_err("Driver Modules are closed");
3071 return -EINVAL;
3072 }
3073
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003074 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3075 data, data_len,
3076 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003077 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078 return -EINVAL;
3079 }
3080 /* Parse and fetch Command Type*/
3081 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003082 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 goto fail;
3084 }
3085 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303086 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
3088 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003089 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003090 goto fail;
3091 }
3092 req_id = nla_get_u32(
3093 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07003094 hdd_debug("Req Id (%d)", req_id);
3095 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003096 switch (cmd_type) {
3097 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
3098 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303099 if (tb[PARAM_NUM_NW]) {
3100 count = nla_get_u32(
3101 tb[PARAM_NUM_NW]);
3102 } else {
3103 hdd_err("Number of networks is not provided");
3104 goto fail;
3105 }
3106
3107 if (count &&
3108 tb[PRAM_SSID_LIST]) {
3109 nla_for_each_nested(curr_attr,
3110 tb[PRAM_SSID_LIST], rem) {
3111 if (nla_parse(tb2,
3112 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
3113 nla_data(curr_attr), nla_len(curr_attr),
3114 NULL)) {
3115 hdd_err("nla_parse failed");
3116 goto fail;
3117 }
3118 /* Parse and Fetch allowed SSID list*/
3119 if (!tb2[PARAM_LIST_SSID]) {
3120 hdd_err("attr allowed ssid failed");
3121 goto fail;
3122 }
3123 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
3124 /*
3125 * Upper Layers include a null termination
3126 * character. Check for the actual permissible
3127 * length of SSID and also ensure not to copy
3128 * the NULL termination character to the driver
3129 * buffer.
3130 */
3131 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
3132 ((buf_len - 1) <=
3133 SIR_MAC_MAX_SSID_LENGTH)) {
3134 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003135 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303136 tb2[PARAM_LIST_SSID], buf_len - 1);
3137 roam_params.ssid_allowed_list[i].length
3138 = buf_len - 1;
3139 hdd_debug("SSID[%d]: %.*s,length = %d",
3140 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 roam_params.ssid_allowed_list[i].length,
3142 roam_params.ssid_allowed_list[i].ssId,
3143 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303144 i++;
3145 } else {
3146 hdd_err("Invalid buffer length");
3147 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148 }
3149 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303150 if (i != count) {
3151 hdd_err("Invalid number of SSIDs i = %d, count = %d",
3152 i, count);
3153 goto fail;
3154 }
3155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07003157 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158 roam_params.num_ssid_allowed_list);
3159 sme_update_roam_params(pHddCtx->hHal, session_id,
3160 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3161 break;
3162 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3163 /* Parse and fetch 5G Boost Threshold */
3164 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003165 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 goto fail;
3167 }
3168 roam_params.raise_rssi_thresh_5g = nla_get_s32(
3169 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003170 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 roam_params.raise_rssi_thresh_5g);
3172 /* Parse and fetch 5G Penalty Threshold */
3173 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003174 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 goto fail;
3176 }
3177 roam_params.drop_rssi_thresh_5g = nla_get_s32(
3178 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003179 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 roam_params.drop_rssi_thresh_5g);
3181 /* Parse and fetch 5G Boost Factor */
3182 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003183 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003184 goto fail;
3185 }
3186 roam_params.raise_factor_5g = nla_get_u32(
3187 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003188 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003189 roam_params.raise_factor_5g);
3190 /* Parse and fetch 5G Penalty factor */
3191 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003192 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193 goto fail;
3194 }
3195 roam_params.drop_factor_5g = nla_get_u32(
3196 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003197 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 roam_params.drop_factor_5g);
3199 /* Parse and fetch 5G Max Boost */
3200 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003201 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 goto fail;
3203 }
3204 roam_params.max_raise_rssi_5g = nla_get_u32(
3205 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07003206 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 roam_params.max_raise_rssi_5g);
3208 /* Parse and fetch Rssi Diff */
3209 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003210 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 goto fail;
3212 }
3213 roam_params.rssi_diff = nla_get_s32(
3214 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07003215 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216 roam_params.rssi_diff);
3217 /* Parse and fetch Alert Rssi Threshold */
3218 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003219 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220 goto fail;
3221 }
3222 roam_params.alert_rssi_threshold = nla_get_u32(
3223 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003224 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 roam_params.alert_rssi_threshold);
3226 sme_update_roam_params(pHddCtx->hHal, session_id,
3227 roam_params,
3228 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3229 break;
3230 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3231 /* Parse and fetch Activate Good Rssi Roam */
3232 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003233 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 goto fail;
3235 }
3236 roam_params.good_rssi_roam = nla_get_s32(
3237 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07003238 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239 roam_params.good_rssi_roam);
3240 sme_update_roam_params(pHddCtx->hHal, session_id,
3241 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3242 break;
3243 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3244 /* Parse and fetch number of preferred BSSID */
3245 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003246 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 goto fail;
3248 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003249 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003251 if (count > MAX_BSSID_FAVORED) {
3252 hdd_err("Preferred BSSID count %u exceeds max %u",
3253 count, MAX_BSSID_FAVORED);
3254 goto fail;
3255 }
3256 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003257 i = 0;
3258 nla_for_each_nested(curr_attr,
3259 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3260 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003261
3262 if (i == count) {
3263 hdd_warn("Ignoring excess Preferred BSSID");
3264 break;
3265 }
3266
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 if (nla_parse(tb2,
3268 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3269 nla_data(curr_attr), nla_len(curr_attr),
3270 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003271 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 goto fail;
3273 }
3274 /* Parse and fetch MAC address */
3275 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003276 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277 goto fail;
3278 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003279 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303281 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003282 hdd_debug(MAC_ADDRESS_STR,
3283 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 /* Parse and fetch preference factor*/
3285 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003286 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003287 goto fail;
3288 }
3289 roam_params.bssid_favored_factor[i] = nla_get_u32(
3290 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003291 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003292 roam_params.bssid_favored_factor[i]);
3293 i++;
3294 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003295 if (i < count)
3296 hdd_warn("Num Preferred BSSID %u less than expected %u",
3297 i, count);
3298 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299 sme_update_roam_params(pHddCtx->hHal, session_id,
3300 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3301 break;
3302 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3303 /* Parse and fetch number of blacklist BSSID */
3304 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003305 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 goto fail;
3307 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003308 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003309 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003310 if (count > MAX_BSSID_AVOID_LIST) {
3311 hdd_err("Blacklist BSSID count %u exceeds max %u",
3312 count, MAX_BSSID_AVOID_LIST);
3313 goto fail;
3314 }
3315 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303317
3318 if (count &&
3319 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3320 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3322 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003323
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303324 if (i == count) {
3325 hdd_warn("Ignoring excess Blacklist BSSID");
3326 break;
3327 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003328
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303329 if (nla_parse(tb2,
3330 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3331 nla_data(curr_attr), nla_len(curr_attr),
3332 NULL)) {
3333 hdd_err("nla_parse failed");
3334 goto fail;
3335 }
3336 /* Parse and fetch MAC address */
3337 if (!tb2[PARAM_SET_BSSID]) {
3338 hdd_err("attr blacklist addr failed");
3339 goto fail;
3340 }
3341 nla_memcpy(
3342 roam_params.bssid_avoid_list[i].bytes,
3343 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3344 hdd_debug(MAC_ADDRESS_STR,
3345 MAC_ADDR_ARRAY(
3346 roam_params.bssid_avoid_list[i].bytes));
3347 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003348 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003350 if (i < count)
3351 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3352 i, count);
3353 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354 sme_update_roam_params(pHddCtx->hHal, session_id,
3355 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3356 break;
3357 }
3358 return 0;
3359fail:
3360 return -EINVAL;
3361}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303362#undef PARAM_NUM_NW
3363#undef PARAM_SET_BSSID
3364#undef PRAM_SSID_LIST
3365#undef PARAM_LIST_SSID
3366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003367
3368/**
3369 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3370 * @wiphy: pointer to wireless wiphy structure.
3371 * @wdev: pointer to wireless_dev structure.
3372 * @data: Pointer to the data to be passed via vendor interface
3373 * @data_len:Length of the data to be passed
3374 *
3375 * Return: Return the Success or Failure code.
3376 */
3377static int
3378wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3379 struct wireless_dev *wdev,
3380 const void *data,
3381 int data_len)
3382{
3383 int ret;
3384
3385 cds_ssr_protect(__func__);
3386 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3387 data, data_len);
3388 cds_ssr_unprotect(__func__);
3389
3390 return ret;
3391}
3392
3393static const struct nla_policy
3394wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3395 +1] = {
3396 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3397};
3398
3399/**
3400 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3401 * @hdd_ctx: HDD context
3402 * @device_mode: device mode
3403 * Return: bool
3404 */
3405static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003406 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407{
3408 hdd_adapter_t *adapter;
3409 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3410 hdd_ap_ctx_t *ap_ctx;
3411 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303412 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003413
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303414 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003416 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303417 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418 adapter = adapter_node->pAdapter;
3419
3420 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003421 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003422 ap_ctx =
3423 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3424
3425 /*
3426 * if there is SAP already running on DFS channel,
3427 * do not disable scan on dfs channels. Note that
3428 * with SAP on DFS, there cannot be conurrency on
3429 * single radio. But then we can have multiple
3430 * radios !!
3431 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003432 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3433 hdd_ctx->hdd_pdev,
3434 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003435 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003436 return true;
3437 }
3438 }
3439
3440 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003441 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442 sta_ctx =
3443 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3444
3445 /*
3446 * if STA is already connected on DFS channel,
3447 * do not disable scan on dfs channels
3448 */
3449 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003450 (CHANNEL_STATE_DFS ==
3451 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3452 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003453 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454 return true;
3455 }
3456 }
3457
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303458 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459 adapter_node,
3460 &next);
3461 adapter_node = next;
3462 }
3463
3464 return false;
3465}
3466
3467/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003468 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003469 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003470 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003471 *
3472 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003473 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003474 * Fails the disable request if any device is active on a DFS channel.
3475 *
3476 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003477 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003478
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003479int wlan_hdd_enable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3480 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303482 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003483 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003485 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
3486 hdd_info("DFS channels are already %s",
3487 enable_dfs_channels ? "enabled" : "disabled");
3488 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003490
3491 if (!enable_dfs_channels) {
3492 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3493 QDF_STA_MODE);
3494 if (err)
3495 return -EOPNOTSUPP;
3496
3497 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3498 QDF_SAP_MODE);
3499 if (err)
3500 return -EOPNOTSUPP;
3501 }
3502
3503 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
3504
3505 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3506
3507 /* pass dfs channel status to regulatory component */
3508 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
3509 enable_dfs_channels);
3510
3511 if (QDF_IS_STATUS_ERROR(status))
3512 hdd_err("Failed to %s DFS channels",
3513 enable_dfs_channels ? "enable" : "disable");
3514
3515 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003516}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003517
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003518/**
3519 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3520 * @wiphy: corestack handler
3521 * @wdev: wireless device
3522 * @data: data
3523 * @data_len: data length
3524 * Return: success(0) or reason code for failure
3525 */
3526static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3527 struct wireless_dev *wdev,
3528 const void *data,
3529 int data_len)
3530{
3531 struct net_device *dev = wdev->netdev;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003532 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3533 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3534 int ret_val;
3535 uint32_t no_dfs_flag = 0;
3536
Jeff Johnson1f61b612016-02-12 16:28:33 -08003537 ENTER_DEV(dev);
3538
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003539 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303540 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003541 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003542
3543 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3544 data, data_len,
3545 wlan_hdd_set_no_dfs_flag_config_policy)) {
3546 hdd_err("invalid attr");
3547 return -EINVAL;
3548 }
3549
3550 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3551 hdd_err("attr dfs flag failed");
3552 return -EINVAL;
3553 }
3554
3555 no_dfs_flag = nla_get_u32(
3556 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3557
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003558 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003559
3560 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003561 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003562 return -EINVAL;
3563 }
3564
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003565 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566 return ret_val;
3567}
3568
3569/**
3570 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3571 *
3572 * @wiphy: wiphy device pointer
3573 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003574 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003575 * @data_len: Buffer length
3576 *
3577 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3578 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3579 *
3580 * Return: EOK or other error codes.
3581 */
3582
3583static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3584 struct wireless_dev *wdev,
3585 const void *data,
3586 int data_len)
3587{
3588 int ret;
3589
3590 cds_ssr_protect(__func__);
3591 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3592 data, data_len);
3593 cds_ssr_unprotect(__func__);
3594
3595 return ret;
3596}
3597
Manikandan Mohan80dea792016-04-28 16:36:48 -07003598static const struct nla_policy
3599wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3600 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3601};
3602
3603/**
3604 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3605 * @wiphy: wiphy device pointer
3606 * @wdev: wireless device pointer
3607 * @data: Vendor command data buffer
3608 * @data_len: Buffer length
3609 *
3610 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3611 * setup WISA Mode features.
3612 *
3613 * Return: Success(0) or reason code for failure
3614 */
3615static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3616 struct wireless_dev *wdev, const void *data, int data_len)
3617{
3618 struct net_device *dev = wdev->netdev;
3619 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3620 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3621 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3622 struct sir_wisa_params wisa;
3623 int ret_val;
3624 QDF_STATUS status;
3625 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003626 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3627 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003628
3629 ENTER_DEV(dev);
3630 ret_val = wlan_hdd_validate_context(hdd_ctx);
3631 if (ret_val)
3632 goto err;
3633
3634 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3635 hdd_err("Command not allowed in FTM mode");
3636 return -EPERM;
3637 }
3638
3639 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3640 wlan_hdd_wisa_cmd_policy)) {
3641 hdd_err("Invalid WISA cmd attributes");
3642 ret_val = -EINVAL;
3643 goto err;
3644 }
3645 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3646 hdd_err("Invalid WISA mode");
3647 ret_val = -EINVAL;
3648 goto err;
3649 }
3650
3651 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003652 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003653 wisa.mode = wisa_mode;
3654 wisa.vdev_id = adapter->sessionId;
3655 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003656 if (!QDF_IS_STATUS_SUCCESS(status)) {
3657 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003658 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003659 }
3660 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003661 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003662 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3663 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003664 adapter->sessionId),
3665 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003666err:
3667 EXIT();
3668 return ret_val;
3669}
3670
3671/**
3672 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3673 * @wiphy: corestack handler
3674 * @wdev: wireless device
3675 * @data: data
3676 * @data_len: data length
3677 *
3678 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3679 * setup WISA mode features.
3680 *
3681 * Return: Success(0) or reason code for failure
3682 */
3683static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3684 struct wireless_dev *wdev,
3685 const void *data,
3686 int data_len)
3687{
3688 int ret;
3689
3690 cds_ssr_protect(__func__);
3691 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3692 cds_ssr_unprotect(__func__);
3693
3694 return ret;
3695}
3696
Anurag Chouhan96919482016-07-13 16:36:57 +05303697/*
3698 * define short names for the global vendor params
3699 * used by __wlan_hdd_cfg80211_get_station_cmd()
3700 */
3701#define STATION_INVALID \
3702 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3703#define STATION_INFO \
3704 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3705#define STATION_ASSOC_FAIL_REASON \
3706 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3707#define STATION_MAX \
3708 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3709
3710static const struct nla_policy
3711hdd_get_station_policy[STATION_MAX + 1] = {
3712 [STATION_INFO] = {.type = NLA_FLAG},
3713 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3714};
3715
3716/**
3717 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3718 * @hdd_ctx: HDD context within host driver
3719 * @wdev: wireless device
3720 *
3721 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3722 * Validate cmd attributes and send the station info to upper layers.
3723 *
3724 * Return: Success(0) or reason code for failure
3725 */
3726static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3727 hdd_adapter_t *adapter)
3728{
3729 struct sk_buff *skb = NULL;
3730 uint32_t nl_buf_len;
3731 hdd_station_ctx_t *hdd_sta_ctx;
3732
3733 nl_buf_len = NLMSG_HDRLEN;
3734 nl_buf_len += sizeof(uint32_t);
3735 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3736
3737 if (!skb) {
3738 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3739 return -ENOMEM;
3740 }
3741
3742 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3743
3744 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3745 hdd_sta_ctx->conn_info.assoc_status_code)) {
3746 hdd_err("put fail");
3747 goto fail;
3748 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303749
3750 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3751 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3752 hdd_sta_ctx->conn_info.cca)) {
3753 hdd_err("put fail");
3754 goto fail;
3755 }
3756
Anurag Chouhan96919482016-07-13 16:36:57 +05303757 return cfg80211_vendor_cmd_reply(skb);
3758fail:
3759 if (skb)
3760 kfree_skb(skb);
3761 return -EINVAL;
3762}
3763
3764/**
3765 * hdd_map_auth_type() - transform auth type specific to
3766 * vendor command
3767 * @auth_type: csr auth type
3768 *
3769 * Return: Success(0) or reason code for failure
3770 */
3771static int hdd_convert_auth_type(uint32_t auth_type)
3772{
3773 uint32_t ret_val;
3774
3775 switch (auth_type) {
3776 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3777 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3778 break;
3779 case eCSR_AUTH_TYPE_SHARED_KEY:
3780 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3781 break;
3782 case eCSR_AUTH_TYPE_WPA:
3783 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3784 break;
3785 case eCSR_AUTH_TYPE_WPA_PSK:
3786 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3787 break;
3788 case eCSR_AUTH_TYPE_AUTOSWITCH:
3789 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3790 break;
3791 case eCSR_AUTH_TYPE_WPA_NONE:
3792 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3793 break;
3794 case eCSR_AUTH_TYPE_RSN:
3795 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3796 break;
3797 case eCSR_AUTH_TYPE_RSN_PSK:
3798 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3799 break;
3800 case eCSR_AUTH_TYPE_FT_RSN:
3801 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3802 break;
3803 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3804 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3805 break;
3806 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3807 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3808 break;
3809 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3810 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3811 break;
3812 case eCSR_AUTH_TYPE_CCKM_WPA:
3813 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3814 break;
3815 case eCSR_AUTH_TYPE_CCKM_RSN:
3816 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3817 break;
3818 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3819 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3820 break;
3821 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3822 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3823 break;
3824 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3825 case eCSR_AUTH_TYPE_FAILED:
3826 case eCSR_AUTH_TYPE_NONE:
3827 default:
3828 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3829 break;
3830 }
3831 return ret_val;
3832}
3833
3834/**
3835 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3836 * vendor command
3837 * @dot11mode: dot11mode
3838 *
3839 * Return: Success(0) or reason code for failure
3840 */
3841static int hdd_convert_dot11mode(uint32_t dot11mode)
3842{
3843 uint32_t ret_val;
3844
3845 switch (dot11mode) {
3846 case eCSR_CFG_DOT11_MODE_11A:
3847 ret_val = QCA_WLAN_802_11_MODE_11A;
3848 break;
3849 case eCSR_CFG_DOT11_MODE_11B:
3850 ret_val = QCA_WLAN_802_11_MODE_11B;
3851 break;
3852 case eCSR_CFG_DOT11_MODE_11G:
3853 ret_val = QCA_WLAN_802_11_MODE_11G;
3854 break;
3855 case eCSR_CFG_DOT11_MODE_11N:
3856 ret_val = QCA_WLAN_802_11_MODE_11N;
3857 break;
3858 case eCSR_CFG_DOT11_MODE_11AC:
3859 ret_val = QCA_WLAN_802_11_MODE_11AC;
3860 break;
3861 case eCSR_CFG_DOT11_MODE_AUTO:
3862 case eCSR_CFG_DOT11_MODE_ABG:
3863 default:
3864 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3865 }
3866 return ret_val;
3867}
3868
3869/**
3870 * hdd_add_tx_bitrate() - add tx bitrate attribute
3871 * @skb: pointer to sk buff
3872 * @hdd_sta_ctx: pointer to hdd station context
3873 * @idx: attribute index
3874 *
3875 * Return: Success(0) or reason code for failure
3876 */
3877static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3878 hdd_station_ctx_t *hdd_sta_ctx,
3879 int idx)
3880{
3881 struct nlattr *nla_attr;
3882 uint32_t bitrate, bitrate_compat;
3883
3884 nla_attr = nla_nest_start(skb, idx);
3885 if (!nla_attr)
3886 goto fail;
3887 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3888 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3889
3890 /* report 16-bit bitrate only if we can */
3891 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3892 if (bitrate > 0 &&
3893 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3894 hdd_err("put fail");
3895 goto fail;
3896 }
3897 if (bitrate_compat > 0 &&
3898 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3899 hdd_err("put fail");
3900 goto fail;
3901 }
3902 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3903 hdd_sta_ctx->conn_info.txrate.nss)) {
3904 hdd_err("put fail");
3905 goto fail;
3906 }
3907 nla_nest_end(skb, nla_attr);
3908 return 0;
3909fail:
3910 return -EINVAL;
3911}
3912
3913/**
3914 * hdd_add_sta_info() - add station info attribute
3915 * @skb: pointer to sk buff
3916 * @hdd_sta_ctx: pointer to hdd station context
3917 * @idx: attribute index
3918 *
3919 * Return: Success(0) or reason code for failure
3920 */
3921static int32_t hdd_add_sta_info(struct sk_buff *skb,
3922 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3923{
3924 struct nlattr *nla_attr;
3925
3926 nla_attr = nla_nest_start(skb, idx);
3927 if (!nla_attr)
3928 goto fail;
3929 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3930 (hdd_sta_ctx->conn_info.signal + 100))) {
3931 hdd_err("put fail");
3932 goto fail;
3933 }
3934 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3935 goto fail;
3936 nla_nest_end(skb, nla_attr);
3937 return 0;
3938fail:
3939 return -EINVAL;
3940}
3941
3942/**
3943 * hdd_add_survey_info() - add survey info attribute
3944 * @skb: pointer to sk buff
3945 * @hdd_sta_ctx: pointer to hdd station context
3946 * @idx: attribute index
3947 *
3948 * Return: Success(0) or reason code for failure
3949 */
3950static int32_t hdd_add_survey_info(struct sk_buff *skb,
3951 hdd_station_ctx_t *hdd_sta_ctx,
3952 int idx)
3953{
3954 struct nlattr *nla_attr;
3955
3956 nla_attr = nla_nest_start(skb, idx);
3957 if (!nla_attr)
3958 goto fail;
3959 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3960 hdd_sta_ctx->conn_info.freq) ||
3961 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3962 (hdd_sta_ctx->conn_info.noise + 100))) {
3963 hdd_err("put fail");
3964 goto fail;
3965 }
3966 nla_nest_end(skb, nla_attr);
3967 return 0;
3968fail:
3969 return -EINVAL;
3970}
3971
3972/**
3973 * hdd_add_link_standard_info() - add link info attribute
3974 * @skb: pointer to sk buff
3975 * @hdd_sta_ctx: pointer to hdd station context
3976 * @idx: attribute index
3977 *
3978 * Return: Success(0) or reason code for failure
3979 */
3980static int32_t
3981hdd_add_link_standard_info(struct sk_buff *skb,
3982 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3983{
3984 struct nlattr *nla_attr;
3985
3986 nla_attr = nla_nest_start(skb, idx);
3987 if (!nla_attr)
3988 goto fail;
3989 if (nla_put(skb,
3990 NL80211_ATTR_SSID,
3991 hdd_sta_ctx->conn_info.SSID.SSID.length,
3992 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3993 hdd_err("put fail");
3994 goto fail;
3995 }
3996 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3997 goto fail;
3998 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3999 goto fail;
4000 nla_nest_end(skb, nla_attr);
4001 return 0;
4002fail:
4003 return -EINVAL;
4004}
4005
4006/**
4007 * hdd_add_ap_standard_info() - add ap info attribute
4008 * @skb: pointer to sk buff
4009 * @hdd_sta_ctx: pointer to hdd station context
4010 * @idx: attribute index
4011 *
4012 * Return: Success(0) or reason code for failure
4013 */
4014static int32_t
4015hdd_add_ap_standard_info(struct sk_buff *skb,
4016 hdd_station_ctx_t *hdd_sta_ctx, int idx)
4017{
4018 struct nlattr *nla_attr;
4019
4020 nla_attr = nla_nest_start(skb, idx);
4021 if (!nla_attr)
4022 goto fail;
4023 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
4024 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
4025 sizeof(hdd_sta_ctx->conn_info.vht_caps),
4026 &hdd_sta_ctx->conn_info.vht_caps)) {
4027 hdd_err("put fail");
4028 goto fail;
4029 }
4030 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
4031 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
4032 sizeof(hdd_sta_ctx->conn_info.ht_caps),
4033 &hdd_sta_ctx->conn_info.ht_caps)) {
4034 hdd_err("put fail");
4035 goto fail;
4036 }
4037 nla_nest_end(skb, nla_attr);
4038 return 0;
4039fail:
4040 return -EINVAL;
4041}
4042
4043/**
4044 * hdd_get_station_info() - send BSS information to supplicant
4045 * @hdd_ctx: pointer to hdd context
4046 * @adapter: pointer to adapter
4047 *
4048 * Return: 0 if success else error status
4049 */
4050static int hdd_get_station_info(hdd_context_t *hdd_ctx,
4051 hdd_adapter_t *adapter)
4052{
4053 struct sk_buff *skb = NULL;
4054 uint8_t *tmp_hs20 = NULL;
4055 uint32_t nl_buf_len;
4056 hdd_station_ctx_t *hdd_sta_ctx;
4057
4058 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4059
4060 nl_buf_len = NLMSG_HDRLEN;
4061 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
4062 sizeof(hdd_sta_ctx->conn_info.freq) +
4063 sizeof(hdd_sta_ctx->conn_info.noise) +
4064 sizeof(hdd_sta_ctx->conn_info.signal) +
4065 (sizeof(uint32_t) * 2) +
4066 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
4067 sizeof(hdd_sta_ctx->conn_info.roam_count) +
4068 sizeof(hdd_sta_ctx->conn_info.authType) +
4069 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
4070 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
4071 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
4072 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
4073 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
4074 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
4075 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
4076 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
4077 1);
4078 }
4079 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
4080 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
4081 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
4082 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
4083
4084
4085 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
4086 if (!skb) {
4087 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
4088 return -ENOMEM;
4089 }
4090
4091 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
4092 LINK_INFO_STANDARD_NL80211_ATTR)) {
4093 hdd_err("put fail");
4094 goto fail;
4095 }
4096 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
4097 AP_INFO_STANDARD_NL80211_ATTR)) {
4098 hdd_err("put fail");
4099 goto fail;
4100 }
4101 if (nla_put_u32(skb, INFO_ROAM_COUNT,
4102 hdd_sta_ctx->conn_info.roam_count) ||
4103 nla_put_u32(skb, INFO_AKM,
4104 hdd_convert_auth_type(
4105 hdd_sta_ctx->conn_info.authType)) ||
4106 nla_put_u32(skb, WLAN802_11_MODE,
4107 hdd_convert_dot11mode(
4108 hdd_sta_ctx->conn_info.dot11Mode))) {
4109 hdd_err("put fail");
4110 goto fail;
4111 }
4112 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
4113 if (nla_put(skb, HT_OPERATION,
4114 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
4115 &hdd_sta_ctx->conn_info.ht_operation)) {
4116 hdd_err("put fail");
4117 goto fail;
4118 }
4119 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
4120 if (nla_put(skb, VHT_OPERATION,
4121 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
4122 &hdd_sta_ctx->conn_info.vht_operation)) {
4123 hdd_err("put fail");
4124 goto fail;
4125 }
4126 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
4127 if (nla_put(skb, AP_INFO_HS20_INDICATION,
4128 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
4129 tmp_hs20 + 1)) {
4130 hdd_err("put fail");
4131 goto fail;
4132 }
4133
4134 return cfg80211_vendor_cmd_reply(skb);
4135fail:
4136 if (skb)
4137 kfree_skb(skb);
4138 return -EINVAL;
4139}
4140
4141/**
4142 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4143 * @wiphy: corestack handler
4144 * @wdev: wireless device
4145 * @data: data
4146 * @data_len: data length
4147 *
4148 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4149 * Validate cmd attributes and send the station info to upper layers.
4150 *
4151 * Return: Success(0) or reason code for failure
4152 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05304153static int
Anurag Chouhan96919482016-07-13 16:36:57 +05304154__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4155 struct wireless_dev *wdev,
4156 const void *data,
4157 int data_len)
4158{
4159 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4160 struct net_device *dev = wdev->netdev;
4161 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4162 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
4163 int32_t status;
4164
4165 ENTER_DEV(dev);
4166 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4167 hdd_err("Command not allowed in FTM mode");
4168 status = -EPERM;
4169 goto out;
4170 }
4171
4172 status = wlan_hdd_validate_context(hdd_ctx);
4173 if (0 != status)
4174 goto out;
4175
4176
4177 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
4178 data, data_len, NULL);
4179 if (status) {
4180 hdd_err("Invalid ATTR");
4181 goto out;
4182 }
4183
4184 /* Parse and fetch Command Type*/
4185 if (tb[STATION_INFO]) {
4186 status = hdd_get_station_info(hdd_ctx, adapter);
4187 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
4188 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
4189 } else {
4190 hdd_err("get station info cmd type failed");
4191 status = -EINVAL;
4192 goto out;
4193 }
4194 EXIT();
4195out:
4196 return status;
4197}
4198
4199/**
4200 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4201 * @wiphy: corestack handler
4202 * @wdev: wireless device
4203 * @data: data
4204 * @data_len: data length
4205 *
4206 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4207 * Validate cmd attributes and send the station info to upper layers.
4208 *
4209 * Return: Success(0) or reason code for failure
4210 */
4211static int32_t
4212hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4213 struct wireless_dev *wdev,
4214 const void *data,
4215 int data_len)
4216{
4217 int ret;
4218
4219 cds_ssr_protect(__func__);
4220 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
4221 cds_ssr_unprotect(__func__);
4222
4223 return ret;
4224}
4225
4226/*
4227 * undef short names defined for get station command
4228 * used by __wlan_hdd_cfg80211_get_station_cmd()
4229 */
4230#undef STATION_INVALID
4231#undef STATION_INFO
4232#undef STATION_ASSOC_FAIL_REASON
4233#undef STATION_MAX
4234
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004235#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4236/**
4237 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4238 * @wiphy: pointer to wireless wiphy structure.
4239 * @wdev: pointer to wireless_dev structure.
4240 * @data: Pointer to the Key data
4241 * @data_len:Length of the data passed
4242 *
4243 * This is called when wlan driver needs to save the keys received via
4244 * vendor specific command.
4245 *
4246 * Return: Return the Success or Failure code.
4247 */
4248static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4249 struct wireless_dev *wdev,
4250 const void *data, int data_len)
4251{
4252 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4253 struct net_device *dev = wdev->netdev;
4254 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4255 hdd_context_t *hdd_ctx_ptr;
4256 int status;
4257
Jeff Johnson1f61b612016-02-12 16:28:33 -08004258 ENTER_DEV(dev);
4259
Anurag Chouhan6d760662016-02-20 16:05:43 +05304260 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 hdd_err("Command not allowed in FTM mode");
4262 return -EPERM;
4263 }
4264
4265 if ((data == NULL) || (data_len == 0) ||
4266 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004267 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004268 return -EINVAL;
4269 }
4270
4271 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4272 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004273 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004274 return -EINVAL;
4275 }
4276
4277 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304278 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004280 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4281 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004282 true,
4283 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304284 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4285 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4287 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4288 return 0;
4289}
4290
4291/**
4292 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4293 * @wiphy: pointer to wireless wiphy structure.
4294 * @wdev: pointer to wireless_dev structure.
4295 * @data: Pointer to the Key data
4296 * @data_len:Length of the data passed
4297 *
4298 * This is called when wlan driver needs to save the keys received via
4299 * vendor specific command.
4300 *
4301 * Return: Return the Success or Failure code.
4302 */
4303static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4304 struct wireless_dev *wdev,
4305 const void *data, int data_len)
4306{
4307 int ret;
4308
4309 cds_ssr_protect(__func__);
4310 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4311 cds_ssr_unprotect(__func__);
4312
4313 return ret;
4314}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004315#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004316
4317static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4318 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4319 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4320 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004321 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322};
4323
4324/**
4325 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4326 * @wiphy: pointer to wireless wiphy structure.
4327 * @wdev: pointer to wireless_dev structure.
4328 * @data: Pointer to the data to be passed via vendor interface
4329 * @data_len:Length of the data to be passed
4330 *
4331 * This is called when wlan driver needs to send wifi driver related info
4332 * (driver/fw version) to the user space application upon request.
4333 *
4334 * Return: Return the Success or Failure code.
4335 */
4336static int
4337__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4338 struct wireless_dev *wdev,
4339 const void *data, int data_len)
4340{
4341 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4342 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004343 tSirVersionString driver_version;
4344 tSirVersionString firmware_version;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004345 const char *hw_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004346 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004347 uint32_t sub_id = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004349 struct sk_buff *reply_skb;
4350 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351
Jeff Johnson1f61b612016-02-12 16:28:33 -08004352 ENTER_DEV(wdev->netdev);
4353
Anurag Chouhan6d760662016-02-20 16:05:43 +05304354 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 hdd_err("Command not allowed in FTM mode");
4356 return -EPERM;
4357 }
4358
4359 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304360 if (status)
4361 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362
4363 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4364 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004365 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004366 return -EINVAL;
4367 }
4368
4369 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004370 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004371 strlcpy(driver_version, QWLAN_VERSIONSTR,
4372 sizeof(driver_version));
4373 skb_len += strlen(driver_version) + 1;
4374 count++;
4375 }
4376
4377 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004378 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4380 &crmid);
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004381 sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
4382 hw_version = hdd_ctx->target_hw_name;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004383 snprintf(firmware_version, sizeof(firmware_version),
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004384 "FW:%d.%d.%d.%d.%d HW:%s", major_spid, minor_spid,
4385 siid, crmid, sub_id, hw_version);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004386 skb_len += strlen(firmware_version) + 1;
4387 count++;
4388 }
4389
4390 if (count == 0) {
4391 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392 return -EINVAL;
4393 }
4394
Ryan Hsu7ac88852016-04-28 10:20:34 -07004395 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4396 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4397
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004398 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004399 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 return -ENOMEM;
4401 }
4402
Ryan Hsu7ac88852016-04-28 10:20:34 -07004403 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4404 if (nla_put_string(reply_skb,
4405 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4406 driver_version))
4407 goto error_nla_fail;
4408 }
4409
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304410 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004411 if (nla_put_string(reply_skb,
4412 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4413 firmware_version))
4414 goto error_nla_fail;
4415 }
4416
4417 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4418 if (nla_put_u32(reply_skb,
4419 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4420 hdd_ctx->radio_index))
4421 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004422 }
4423
4424 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004425
4426error_nla_fail:
4427 hdd_err("nla put fail");
4428 kfree_skb(reply_skb);
4429 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430}
4431
4432/**
4433 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4434 * @wiphy: pointer to wireless wiphy structure.
4435 * @wdev: pointer to wireless_dev structure.
4436 * @data: Pointer to the data to be passed via vendor interface
4437 * @data_len:Length of the data to be passed
4438 *
4439 * This is called when wlan driver needs to send wifi driver related info
4440 * (driver/fw version) to the user space application upon request.
4441 *
4442 * Return: Return the Success or Failure code.
4443 */
4444static int
4445wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4446 struct wireless_dev *wdev,
4447 const void *data, int data_len)
4448{
4449 int ret;
4450
4451 cds_ssr_protect(__func__);
4452 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4453 cds_ssr_unprotect(__func__);
4454
4455 return ret;
4456}
4457
4458/**
4459 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4460 * @wiphy: pointer to wireless wiphy structure.
4461 * @wdev: pointer to wireless_dev structure.
4462 * @data: Pointer to the data to be passed via vendor interface
4463 * @data_len:Length of the data to be passed
4464 *
4465 * This is called by userspace to know the supported logger features
4466 *
4467 * Return: Return the Success or Failure code.
4468 */
4469static int
4470__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4471 struct wireless_dev *wdev,
4472 const void *data, int data_len)
4473{
4474 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4475 int status;
4476 uint32_t features;
4477 struct sk_buff *reply_skb = NULL;
4478
Jeff Johnson1f61b612016-02-12 16:28:33 -08004479 ENTER_DEV(wdev->netdev);
4480
Anurag Chouhan6d760662016-02-20 16:05:43 +05304481 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482 hdd_err("Command not allowed in FTM mode");
4483 return -EPERM;
4484 }
4485
4486 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304487 if (status)
4488 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004489
4490 features = 0;
4491
4492 if (hdd_is_memdump_supported())
4493 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4494 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4495 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4496 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4497
4498 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4499 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4500 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004501 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 return -ENOMEM;
4503 }
4504
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004505 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004506 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4507 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004508 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509 kfree_skb(reply_skb);
4510 return -EINVAL;
4511 }
4512
4513 return cfg80211_vendor_cmd_reply(reply_skb);
4514}
4515
4516/**
4517 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4518 * @wiphy: pointer to wireless wiphy structure.
4519 * @wdev: pointer to wireless_dev structure.
4520 * @data: Pointer to the data to be passed via vendor interface
4521 * @data_len:Length of the data to be passed
4522 *
4523 * This is called by userspace to know the supported logger features
4524 *
4525 * Return: Return the Success or Failure code.
4526 */
4527static int
4528wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4529 struct wireless_dev *wdev,
4530 const void *data, int data_len)
4531{
4532 int ret;
4533
4534 cds_ssr_protect(__func__);
4535 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4536 data, data_len);
4537 cds_ssr_unprotect(__func__);
4538
4539 return ret;
4540}
4541
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004542#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543/**
4544 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304545 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 * @bssid: pointer to bssid of roamed AP.
4547 * @req_rsn_ie: Pointer to request RSN IE
4548 * @req_rsn_len: Length of the request RSN IE
4549 * @rsp_rsn_ie: Pointer to response RSN IE
4550 * @rsp_rsn_len: Length of the response RSN IE
4551 * @roam_info_ptr: Pointer to the roaming related information
4552 *
4553 * This is called when wlan driver needs to send the roaming and
4554 * authorization information after roaming.
4555 *
4556 * The information that would be sent is the request RSN IE, response
4557 * RSN IE and BSSID of the newly roamed AP.
4558 *
4559 * If the Authorized status is authenticated, then additional parameters
4560 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4561 * supplicant.
4562 *
4563 * The supplicant upon receiving this event would ignore the legacy
4564 * cfg80211_roamed call and use the entire information from this event.
4565 * The cfg80211_roamed should still co-exist since the kernel will
4566 * make use of the parameters even if the supplicant ignores it.
4567 *
4568 * Return: Return the Success or Failure code.
4569 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304570int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004571 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4572 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4573{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304574 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004576 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004577 ENTER();
4578
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304579 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004582 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004583 !roam_info_ptr->roamSynchInProgress)
4584 return 0;
4585
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004586 /*
4587 * The user space has issued a disconnect when roaming is in
4588 * progress. The disconnect should be honored gracefully.
4589 * If the roaming is complete and the roam event is sent
4590 * back to the user space, it will get confused as it is
4591 * expecting a disconnect event. So, do not send the event
4592 * and handle the disconnect later.
4593 */
4594 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004595 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004596 return 0;
4597 }
4598
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004599 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304600 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4602 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4603 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004604 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4606 GFP_KERNEL);
4607
4608 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004609 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004610 return -EINVAL;
4611 }
4612
4613 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4614 ETH_ALEN, bssid) ||
4615 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4616 req_rsn_len, req_rsn_ie) ||
4617 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4618 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004619 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620 goto nla_put_failure;
4621 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004622 if (roam_info_ptr->synchAuthStatus ==
4623 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004624 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004625 if (nla_put_u8(skb,
4626 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4627 hdd_err("nla put fail");
4628 goto nla_put_failure;
4629 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004630 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4631 /* if FT or CCKM connection: dont send replay counter */
4632 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4633 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4634 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4635 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4636 nla_put(skb,
4637 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4638 SIR_REPLAY_CTR_LEN,
4639 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004640 hdd_err("non FT/non CCKM connection");
4641 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004642 goto nla_put_failure;
4643 }
4644 if (nla_put(skb,
4645 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4646 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4647 nla_put(skb,
4648 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4649 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4650 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 goto nla_put_failure;
4652 }
4653 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004654 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4656 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004657 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658 goto nla_put_failure;
4659 }
4660 }
4661
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304662 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4663 roam_info_ptr->synchAuthStatus,
4664 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004665
4666 /*
4667 * Add subnet change status if subnet has changed
4668 * 0 = unchanged
4669 * 1 = changed
4670 * 2 = unknown
4671 */
4672 if (roam_info_ptr->subnet_change_status) {
4673 if (nla_put_u8(skb,
4674 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4675 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004676 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004677 goto nla_put_failure;
4678 }
4679 }
4680
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 cfg80211_vendor_event(skb, GFP_KERNEL);
4682 return 0;
4683
4684nla_put_failure:
4685 kfree_skb(skb);
4686 return -EINVAL;
4687}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004688#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689
lifeng907edd62017-05-12 10:10:36 +08004690#define ANT_DIV_PROBE_PERIOD \
4691 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
4692#define ANT_DIV_STAY_PERIOD \
4693 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
4694#define ANT_DIV_SNR_DIFF \
4695 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
4696#define ANT_DIV_PROBE_DWELL_TIME \
4697 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
4698#define ANT_DIV_MGMT_SNR_WEIGHT \
4699 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
4700#define ANT_DIV_DATA_SNR_WEIGHT \
4701 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
4702#define ANT_DIV_ACK_SNR_WEIGHT \
4703 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004704static const struct nla_policy
4705wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4706
4707 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4708 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4709 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304710 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304711 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4712 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004713 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4714 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4715 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4716 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4717 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304718 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08004719 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
4720 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
4721 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
4722 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
4723 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
4724 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
4725 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004726};
4727
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004728/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304729 * wlan_hdd_add_qcn_ie() - Add QCN IE to a given IE buffer
4730 * @ie_data: IE buffer
4731 * @ie_len: length of the @ie_data
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304732 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304733 * Return: QDF_STATUS
4734 */
4735static QDF_STATUS wlan_hdd_add_qcn_ie(uint8_t *ie_data, uint16_t *ie_len)
4736{
4737 tDot11fIEQCN_IE qcn_ie;
4738 uint8_t qcn_ie_hdr[QCN_IE_HDR_LEN]
4739 = {IE_EID_VENDOR, DOT11F_IE_QCN_IE_MAX_LEN,
4740 0x8C, 0xFD, 0xF0, 0x1};
4741
4742 if (((*ie_len) + QCN_IE_HDR_LEN +
4743 QCN_IE_VERSION_SUBATTR_DATA_LEN) > MAX_DEFAULT_SCAN_IE_LEN) {
4744 hdd_err("IE buffer not enough for QCN IE");
4745 return QDF_STATUS_E_FAILURE;
4746 }
4747
4748 /* Add QCN IE header */
4749 qdf_mem_copy(ie_data + (*ie_len), qcn_ie_hdr, QCN_IE_HDR_LEN);
4750 (*ie_len) += QCN_IE_HDR_LEN;
4751
4752 /* Retrieve Version sub-attribute data */
4753 populate_dot11f_qcn_ie(&qcn_ie);
4754
4755 /* Add QCN IE data[version sub attribute] */
4756 qdf_mem_copy(ie_data + (*ie_len), qcn_ie.version,
4757 (QCN_IE_VERSION_SUBATTR_LEN));
4758 (*ie_len) += (QCN_IE_VERSION_SUBATTR_LEN);
4759
4760 return QDF_STATUS_SUCCESS;
4761}
4762
4763/**
4764 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4765 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304766 * @adapter: Pointer to HDD adapter
4767 * @ie_data: Pointer to Scan IEs buffer
4768 * @ie_len: Length of Scan IEs
4769 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304770 * This API is used to store the default scan ies received from
4771 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
4772 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304773 * Return: 0 on success; error number otherwise
4774 */
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304775static int wlan_hdd_save_default_scan_ies(hdd_context_t *hdd_ctx,
4776 hdd_adapter_t *adapter,
4777 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304778{
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304779 hdd_scaninfo_t *scan_info = &adapter->scan_info;
4780 bool add_qcn_ie = hdd_ctx->config->qcn_ie_support;
4781
4782 if (!scan_info)
4783 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304784
4785 if (scan_info->default_scan_ies) {
4786 qdf_mem_free(scan_info->default_scan_ies);
4787 scan_info->default_scan_ies = NULL;
4788 }
4789
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304790 scan_info->default_scan_ies_len = ie_len;
4791
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304792 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304793 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304794
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304795 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304796 if (!scan_info->default_scan_ies) {
4797 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304798 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304799 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304800
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304801 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
4802 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304803
4804 /* Add QCN IE if g_qcn_ie_support INI is enabled */
4805 if (add_qcn_ie)
4806 wlan_hdd_add_qcn_ie(scan_info->default_scan_ies,
4807 &(scan_info->default_scan_ies_len));
4808
4809 hdd_debug("Saved default scan IE:");
4810 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
4811 (uint8_t *) scan_info->default_scan_ies,
4812 scan_info->default_scan_ies_len);
4813
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304814 return 0;
4815}
4816
4817/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004818 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4819 * vendor command
4820 *
4821 * @wiphy: wiphy device pointer
4822 * @wdev: wireless device pointer
4823 * @data: Vendor command data buffer
4824 * @data_len: Buffer length
4825 *
4826 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4827 *
4828 * Return: Error code.
4829 */
4830static int
4831__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4832 struct wireless_dev *wdev,
4833 const void *data,
4834 int data_len)
4835{
4836 struct net_device *dev = wdev->netdev;
4837 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4838 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4839 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4840 int ret_val = 0;
4841 u32 modulated_dtim;
4842 u16 stats_avg_factor;
4843 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304844 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004845 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004846 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304847 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304848 int attr_len;
4849 int access_policy = 0;
4850 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4851 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304852 uint16_t scan_ie_len = 0;
4853 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304854 struct sir_set_tx_rx_aggregation_size request;
4855 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004856 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004857 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004858 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304859 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08004860 uint32_t ant_div_usrcfg;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304861
Jeff Johnson1f61b612016-02-12 16:28:33 -08004862 ENTER_DEV(dev);
4863
Anurag Chouhan6d760662016-02-20 16:05:43 +05304864 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865 hdd_err("Command not allowed in FTM mode");
4866 return -EPERM;
4867 }
4868
4869 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304870 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004871 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872
4873 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4874 data, data_len,
4875 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004876 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004877 return -EINVAL;
4878 }
4879
Krunal Sonie3531942016-04-12 17:43:53 -07004880 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4881 ftm_capab = nla_get_u32(tb[
4882 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4883 hdd_ctx->config->fine_time_meas_cap =
4884 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4885 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304886 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004887 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004888 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4889 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004890 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004891 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4892 hdd_ctx->config->fine_time_meas_cap);
4893 }
4894
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4896 modulated_dtim = nla_get_u32(
4897 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4898
4899 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4900 adapter->sessionId,
4901 modulated_dtim);
4902
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304903 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904 ret_val = -EPERM;
4905 }
4906
Kapil Gupta6213c012016-09-02 19:39:09 +05304907 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4908 qpower = nla_get_u8(
4909 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4910 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4911 ret_val = -EINVAL;
4912 }
4913
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4915 stats_avg_factor = nla_get_u16(
4916 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4917 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4918 adapter->sessionId,
4919 stats_avg_factor);
4920
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304921 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004922 ret_val = -EPERM;
4923 }
4924
4925
4926 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4927 guard_time = nla_get_u32(
4928 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4929 status = sme_configure_guard_time(hdd_ctx->hHal,
4930 adapter->sessionId,
4931 guard_time);
4932
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304933 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004934 ret_val = -EPERM;
4935 }
4936
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304937 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4938 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4939 attr_len = nla_len(
4940 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4941 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004942 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304943 attr_len);
4944 return -EINVAL;
4945 }
4946
4947 nla_memcpy(&vendor_ie,
4948 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4949 attr_len);
4950 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004951 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304952 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304953 }
4954
4955 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4956 access_policy = (int) nla_get_u32(
4957 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4958 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4959 (access_policy >
4960 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004961 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304962 access_policy);
4963 return -EINVAL;
4964 }
4965 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004966 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304967 access_policy);
4968 }
4969
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004970 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4971 retry = nla_get_u8(tb[
4972 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4973 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4974 CFG_NON_AGG_RETRY_MAX : retry;
4975 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4976 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4977 retry, PDEV_CMD);
4978 }
4979
4980 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4981 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4982 retry = retry > CFG_AGG_RETRY_MAX ?
4983 CFG_AGG_RETRY_MAX : retry;
4984
4985 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4986 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4987 CFG_AGG_RETRY_MIN : retry;
4988 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4989 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4990 retry, PDEV_CMD);
4991 }
4992
4993 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4994 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4995 retry = retry > CFG_MGMT_RETRY_MAX ?
4996 CFG_MGMT_RETRY_MAX : retry;
4997 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4998 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4999 retry, PDEV_CMD);
5000 }
5001
5002 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
5003 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
5004 retry = retry > CFG_CTRL_RETRY_MAX ?
5005 CFG_CTRL_RETRY_MAX : retry;
5006 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
5007 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5008 retry, PDEV_CMD);
5009 }
5010
5011 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
5012 delay = nla_get_u8(tb[
5013 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
5014 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
5015 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08005016 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005017 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
5018 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08005019 abs_delay, PDEV_CMD);
5020 }
5021
5022 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
5023 abs_delay = nla_get_u8(tb[
5024 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
5025 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
5026 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5027 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005028 }
5029
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305030 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
5031 tx_fail_count = nla_get_u32(
5032 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
5033 if (tx_fail_count) {
5034 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
5035 adapter->sessionId, tx_fail_count);
5036 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005037 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305038 status);
5039 return -EINVAL;
5040 }
5041 }
5042 }
5043
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305044 if (vendor_ie_present && access_policy_present) {
5045 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
5046 access_policy =
5047 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305048 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305049 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305050 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305051
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005052 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305053 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
5054 adapter->sessionId, &vendor_ie[0],
5055 access_policy);
5056 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005057 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305058 return -EINVAL;
5059 }
5060 }
5061
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305062 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
5063 set_value = nla_get_u8(
5064 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005065 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305066 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
5067 }
5068
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305069 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
5070 scan_ie_len = nla_len(
5071 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005072 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305073 scan_ie_len, adapter->sessionId,
5074 adapter->device_mode);
5075 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
5076 scan_ie = (uint8_t *) nla_data(tb
5077 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305078
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305079 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
5080 scan_ie, scan_ie_len))
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305081 hdd_err("Failed to save default scan IEs");
5082
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305083 if (adapter->device_mode == QDF_STA_MODE) {
5084 status = sme_set_default_scan_ie(hdd_ctx->hHal,
5085 adapter->sessionId, scan_ie,
5086 scan_ie_len);
5087 if (QDF_STATUS_SUCCESS != status)
5088 ret_val = -EPERM;
5089 }
5090 } else
5091 ret_val = -EPERM;
5092 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05305093
5094 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
5095 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
5096 /* if one is specified, both must be specified */
5097 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
5098 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
5099 hdd_err("Both TX and RX MPDU Aggregation required");
5100 return -EINVAL;
5101 }
5102
5103 request.tx_aggregation_size = nla_get_u8(
5104 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
5105 request.rx_aggregation_size = nla_get_u8(
5106 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
5107 request.vdev_id = adapter->sessionId;
5108
5109 if (request.tx_aggregation_size >=
5110 CFG_TX_AGGREGATION_SIZE_MIN &&
5111 request.tx_aggregation_size <=
5112 CFG_TX_AGGREGATION_SIZE_MAX &&
5113 request.rx_aggregation_size >=
5114 CFG_RX_AGGREGATION_SIZE_MIN &&
5115 request.rx_aggregation_size <=
5116 CFG_RX_AGGREGATION_SIZE_MAX) {
5117 qdf_status = wma_set_tx_rx_aggregation_size(&request);
5118 if (qdf_status != QDF_STATUS_SUCCESS) {
5119 hdd_err("failed to set aggr sizes err %d",
5120 qdf_status);
5121 ret_val = -EPERM;
5122 }
5123 } else {
5124 hdd_err("TX %d RX %d MPDU aggr size not in range",
5125 request.tx_aggregation_size,
5126 request.rx_aggregation_size);
5127 ret_val = -EINVAL;
5128 }
5129 }
5130
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305131 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
5132 uint8_t ignore_assoc_disallowed;
5133
5134 ignore_assoc_disallowed
5135 = nla_get_u8(tb[
5136 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005137 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305138 ignore_assoc_disallowed);
5139 if ((ignore_assoc_disallowed <
5140 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
5141 (ignore_assoc_disallowed >
5142 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
5143 return -EPERM;
5144
5145 sme_update_session_param(hdd_ctx->hHal,
5146 adapter->sessionId,
5147 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
5148 ignore_assoc_disallowed);
5149 }
5150
lifeng907edd62017-05-12 10:10:36 +08005151#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
5152 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
5153
5154#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
5155 ((1<<27)|(snr_diff&0x1fff))
5156
5157#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
5158 ((1<<28)|(probe_dwell_time&0x1fff))
5159
5160#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
5161 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
5162 (ack_snr_weight&0xff))
5163
5164 if (tb[ANT_DIV_PROBE_PERIOD] ||
5165 tb[ANT_DIV_STAY_PERIOD]) {
5166
5167 if (!tb[ANT_DIV_PROBE_PERIOD] ||
5168 !tb[ANT_DIV_STAY_PERIOD]) {
5169 hdd_err("Both probe and stay period required");
5170 return -EINVAL;
5171 }
5172
5173 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
5174 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
5175 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
5176 hdd_debug("ant div set period: %x", ant_div_usrcfg);
5177 ret_val = wma_cli_set_command((int)adapter->sessionId,
5178 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5179 ant_div_usrcfg, PDEV_CMD);
5180 if (ret_val) {
5181 hdd_err("Failed to set ant div period");
5182 return ret_val;
5183 }
5184 }
5185
5186 if (tb[ANT_DIV_SNR_DIFF]) {
5187 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
5188 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
5189 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
5190 ret_val = wma_cli_set_command((int)adapter->sessionId,
5191 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5192 ant_div_usrcfg, PDEV_CMD);
5193 if (ret_val) {
5194 hdd_err("Failed to set ant snr diff");
5195 return ret_val;
5196 }
5197 }
5198
5199 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
5200 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
5201 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
5202 hdd_debug("ant div set probe dewll time: %x",
5203 ant_div_usrcfg);
5204 ret_val = wma_cli_set_command((int)adapter->sessionId,
5205 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5206 ant_div_usrcfg, PDEV_CMD);
5207 if (ret_val) {
5208 hdd_err("Failed to set ant div probe dewll time");
5209 return ret_val;
5210 }
5211 }
5212
5213 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5214 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5215 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5216
5217 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5218 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5219 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5220 hdd_err("Mgmt snr, data snr and ack snr weight are required");
5221 return -EINVAL;
5222 }
5223
5224 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
5225 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
5226 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
5227 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
5228 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
5229 ret_val = wma_cli_set_command((int)adapter->sessionId,
5230 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5231 ant_div_usrcfg, PDEV_CMD);
5232 if (ret_val) {
5233 hdd_err("Failed to set ant div weight");
5234 return ret_val;
5235 }
5236 }
5237
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005238 return ret_val;
5239}
5240
5241/**
5242 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
5243 * vendor command
5244 *
5245 * @wiphy: wiphy device pointer
5246 * @wdev: wireless device pointer
5247 * @data: Vendor command data buffer
5248 * @data_len: Buffer length
5249 *
5250 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
5251 *
5252 * Return: EOK or other error codes.
5253 */
5254static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
5255 struct wireless_dev *wdev,
5256 const void *data,
5257 int data_len)
5258{
5259 int ret;
5260
5261 cds_ssr_protect(__func__);
5262 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
5263 data, data_len);
5264 cds_ssr_unprotect(__func__);
5265
5266 return ret;
5267}
5268
5269static const struct
5270nla_policy
5271qca_wlan_vendor_wifi_logger_start_policy
5272[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
5273 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
5274 = {.type = NLA_U32 },
5275 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
5276 = {.type = NLA_U32 },
5277 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
5278 = {.type = NLA_U32 },
5279};
5280
5281/**
5282 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
5283 * or disable the collection of packet statistics from the firmware
5284 * @wiphy: WIPHY structure pointer
5285 * @wdev: Wireless device structure pointer
5286 * @data: Pointer to the data received
5287 * @data_len: Length of the data received
5288 *
5289 * This function enables or disables the collection of packet statistics from
5290 * the firmware
5291 *
5292 * Return: 0 on success and errno on failure
5293 */
5294static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5295 struct wireless_dev *wdev,
5296 const void *data,
5297 int data_len)
5298{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305299 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5301 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
5302 struct sir_wifi_start_log start_log;
5303
Jeff Johnson1f61b612016-02-12 16:28:33 -08005304 ENTER_DEV(wdev->netdev);
5305
Anurag Chouhan6d760662016-02-20 16:05:43 +05305306 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005307 hdd_err("Command not allowed in FTM mode");
5308 return -EPERM;
5309 }
5310
5311 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305312 if (status)
5313 return status;
5314
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05305315 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
5316 hdd_err("Driver Modules are closed, can not start logger");
5317 return -EINVAL;
5318 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005319
5320 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
5321 data, data_len,
5322 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005323 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324 return -EINVAL;
5325 }
5326
5327 /* Parse and fetch ring id */
5328 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005329 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005330 return -EINVAL;
5331 }
5332 start_log.ring_id = nla_get_u32(
5333 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005334 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005335
5336 /* Parse and fetch verbose level */
5337 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005338 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005339 return -EINVAL;
5340 }
5341 start_log.verbose_level = nla_get_u32(
5342 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005343 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005344
5345 /* Parse and fetch flag */
5346 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005347 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348 return -EINVAL;
5349 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05305350 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005352 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005353
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305354 /* size is buff size which can be set using iwpriv command*/
5355 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05305356 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305357
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005358 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
5359
5360 if (start_log.ring_id == RING_ID_WAKELOCK) {
5361 /* Start/stop wakelock events */
5362 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
5363 cds_set_wakelock_logging(true);
5364 else
5365 cds_set_wakelock_logging(false);
5366 return 0;
5367 }
5368
5369 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305370 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005371 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 status);
5373 return -EINVAL;
5374 }
5375 return 0;
5376}
5377
5378/**
5379 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
5380 * or disable the collection of packet statistics from the firmware
5381 * @wiphy: WIPHY structure pointer
5382 * @wdev: Wireless device structure pointer
5383 * @data: Pointer to the data received
5384 * @data_len: Length of the data received
5385 *
5386 * This function is used to enable or disable the collection of packet
5387 * statistics from the firmware
5388 *
5389 * Return: 0 on success and errno on failure
5390 */
5391static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5392 struct wireless_dev *wdev,
5393 const void *data,
5394 int data_len)
5395{
5396 int ret = 0;
5397
5398 cds_ssr_protect(__func__);
5399 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5400 wdev, data, data_len);
5401 cds_ssr_unprotect(__func__);
5402
5403 return ret;
5404}
5405
5406static const struct
5407nla_policy
5408qca_wlan_vendor_wifi_logger_get_ring_data_policy
5409[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5410 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5411 = {.type = NLA_U32 },
5412};
5413
5414/**
5415 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5416 * @wiphy: WIPHY structure pointer
5417 * @wdev: Wireless device structure pointer
5418 * @data: Pointer to the data received
5419 * @data_len: Length of the data received
5420 *
5421 * This function is used to flush or retrieve the per packet statistics from
5422 * the driver
5423 *
5424 * Return: 0 on success and errno on failure
5425 */
5426static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5427 struct wireless_dev *wdev,
5428 const void *data,
5429 int data_len)
5430{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305431 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005432 uint32_t ring_id;
5433 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5434 struct nlattr *tb
5435 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5436
Jeff Johnson1f61b612016-02-12 16:28:33 -08005437 ENTER_DEV(wdev->netdev);
5438
Anurag Chouhan6d760662016-02-20 16:05:43 +05305439 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440 hdd_err("Command not allowed in FTM mode");
5441 return -EPERM;
5442 }
5443
5444 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305445 if (status)
5446 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447
5448 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5449 data, data_len,
5450 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005451 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452 return -EINVAL;
5453 }
5454
5455 /* Parse and fetch ring id */
5456 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005457 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005458 return -EINVAL;
5459 }
5460
5461 ring_id = nla_get_u32(
5462 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5463
5464 if (ring_id == RING_ID_PER_PACKET_STATS) {
5465 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005466 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305467 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5468 /*
5469 * As part of DRIVER ring ID, flush both driver and fw logs.
5470 * For other Ring ID's driver doesn't have any rings to flush
5471 */
5472 hdd_notice("Bug report triggered by framework");
5473
5474 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5475 WLAN_LOG_INDICATOR_FRAMEWORK,
5476 WLAN_LOG_REASON_CODE_UNUSED,
5477 true, false);
5478 if (QDF_STATUS_SUCCESS != status) {
5479 hdd_err("Failed to trigger bug report");
5480 return -EINVAL;
5481 }
5482 } else {
5483 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5484 WLAN_LOG_INDICATOR_FRAMEWORK,
5485 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005486 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487 return 0;
5488}
5489
5490/**
5491 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5492 * @wiphy: WIPHY structure pointer
5493 * @wdev: Wireless device structure pointer
5494 * @data: Pointer to the data received
5495 * @data_len: Length of the data received
5496 *
5497 * This function is used to flush or retrieve the per packet statistics from
5498 * the driver
5499 *
5500 * Return: 0 on success and errno on failure
5501 */
5502static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5503 struct wireless_dev *wdev,
5504 const void *data,
5505 int data_len)
5506{
5507 int ret = 0;
5508
5509 cds_ssr_protect(__func__);
5510 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5511 wdev, data, data_len);
5512 cds_ssr_unprotect(__func__);
5513
5514 return ret;
5515}
5516
5517#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5518/**
5519 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5520 * @hdd_ctx: HDD context
5521 * @request_id: [input] request id
5522 * @pattern_id: [output] pattern id
5523 *
5524 * This function loops through request id to pattern id array
5525 * if the slot is available, store the request id and return pattern id
5526 * if entry exists, return the pattern id
5527 *
5528 * Return: 0 on success and errno on failure
5529 */
5530static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5531 uint32_t request_id,
5532 uint8_t *pattern_id)
5533{
5534 uint32_t i;
5535
5536 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5537 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5538 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5539 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5540 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5541 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5542 return 0;
5543 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5544 request_id) {
5545 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5546 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5547 return 0;
5548 }
5549 }
5550 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5551 return -EINVAL;
5552}
5553
5554/**
5555 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5556 * @hdd_ctx: HDD context
5557 * @request_id: [input] request id
5558 * @pattern_id: [output] pattern id
5559 *
5560 * This function loops through request id to pattern id array
5561 * reset request id to 0 (slot available again) and
5562 * return pattern id
5563 *
5564 * Return: 0 on success and errno on failure
5565 */
5566static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5567 uint32_t request_id,
5568 uint8_t *pattern_id)
5569{
5570 uint32_t i;
5571
5572 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5573 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5574 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5575 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5576 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5577 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5578 return 0;
5579 }
5580 }
5581 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5582 return -EINVAL;
5583}
5584
5585
5586/*
5587 * define short names for the global vendor params
5588 * used by __wlan_hdd_cfg80211_offloaded_packets()
5589 */
5590#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5591#define PARAM_REQUEST_ID \
5592 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5593#define PARAM_CONTROL \
5594 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5595#define PARAM_IP_PACKET \
5596 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5597#define PARAM_SRC_MAC_ADDR \
5598 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5599#define PARAM_DST_MAC_ADDR \
5600 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5601#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5602
5603/**
5604 * wlan_hdd_add_tx_ptrn() - add tx pattern
5605 * @adapter: adapter pointer
5606 * @hdd_ctx: hdd context
5607 * @tb: nl attributes
5608 *
5609 * This function reads the NL attributes and forms a AddTxPtrn message
5610 * posts it to SME.
5611 *
5612 */
5613static int
5614wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5615 struct nlattr **tb)
5616{
5617 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305618 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005619 uint32_t request_id, ret, len;
5620 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305621 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005622 uint16_t eth_type = htons(ETH_P_IP);
5623
5624 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005625 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005626 return -ENOTSUPP;
5627 }
5628
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305629 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005630 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005631 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632 return -ENOMEM;
5633 }
5634
5635 /* Parse and fetch request Id */
5636 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005637 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005638 goto fail;
5639 }
5640
5641 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5642 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005643 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005644 return -EINVAL;
5645 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005646 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005647
5648 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005649 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650 goto fail;
5651 }
5652 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005653 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005654 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005655 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005656 goto fail;
5657 }
5658
5659 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005660 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005661 goto fail;
5662 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005663 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305664 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005665 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005666 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005667
Anurag Chouhanc5548422016-02-24 18:33:27 +05305668 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005669 &adapter->macAddressCurrent)) {
5670 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005671 goto fail;
5672 }
5673
5674 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005675 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005676 goto fail;
5677 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305678 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005679 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005680 MAC_ADDR_ARRAY(dst_addr.bytes));
5681
5682 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005683 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005684 goto fail;
5685 }
5686 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005687 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005688
5689 if (add_req->ucPtrnSize < 0 ||
5690 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5691 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005692 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005693 add_req->ucPtrnSize);
5694 goto fail;
5695 }
5696
5697 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305698 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305699 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305700 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305701 QDF_MAC_ADDR_SIZE);
5702 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305703 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005704 len += 2;
5705
5706 /*
5707 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5708 * ------------------------------------------------------------
5709 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5710 * ------------------------------------------------------------
5711 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305712 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005713 nla_data(tb[PARAM_IP_PACKET]),
5714 add_req->ucPtrnSize);
5715 add_req->ucPtrnSize += len;
5716
5717 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5718 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005719 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005720 goto fail;
5721 }
5722 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005723 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005724
5725 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305726 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005727 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005728 goto fail;
5729 }
5730
5731 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305732 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733 return 0;
5734
5735fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305736 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005737 return -EINVAL;
5738}
5739
5740/**
5741 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5742 * @adapter: adapter pointer
5743 * @hdd_ctx: hdd context
5744 * @tb: nl attributes
5745 *
5746 * This function reads the NL attributes and forms a DelTxPtrn message
5747 * posts it to SME.
5748 *
5749 */
5750static int
5751wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5752 struct nlattr **tb)
5753{
5754 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305755 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005756 uint32_t request_id, ret;
5757 uint8_t pattern_id = 0;
5758
5759 /* Parse and fetch request Id */
5760 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005761 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005762 return -EINVAL;
5763 }
5764 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5765 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005766 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005767 return -EINVAL;
5768 }
5769
5770 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5771 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005772 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005773 return -EINVAL;
5774 }
5775
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305776 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005777 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005778 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779 return -ENOMEM;
5780 }
5781
Anurag Chouhanc5548422016-02-24 18:33:27 +05305782 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005783 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005784 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005785 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005786 request_id, del_req->ucPtrnId);
5787
5788 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305789 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005790 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791 goto fail;
5792 }
5793
5794 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305795 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796 return 0;
5797
5798fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305799 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005800 return -EINVAL;
5801}
5802
5803
5804/**
5805 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5806 * @wiphy: Pointer to wireless phy
5807 * @wdev: Pointer to wireless device
5808 * @data: Pointer to data
5809 * @data_len: Data length
5810 *
5811 * Return: 0 on success, negative errno on failure
5812 */
5813static int
5814__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5815 struct wireless_dev *wdev,
5816 const void *data,
5817 int data_len)
5818{
5819 struct net_device *dev = wdev->netdev;
5820 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5821 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5822 struct nlattr *tb[PARAM_MAX + 1];
5823 uint8_t control;
5824 int ret;
5825 static const struct nla_policy policy[PARAM_MAX + 1] = {
5826 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5827 [PARAM_CONTROL] = { .type = NLA_U32 },
5828 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305829 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005830 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305831 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005832 [PARAM_PERIOD] = { .type = NLA_U32 },
5833 };
5834
Jeff Johnson1f61b612016-02-12 16:28:33 -08005835 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005836
Anurag Chouhan6d760662016-02-20 16:05:43 +05305837 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838 hdd_err("Command not allowed in FTM mode");
5839 return -EPERM;
5840 }
5841
5842 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305843 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005845
5846 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005847 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005848 return -ENOTSUPP;
5849 }
5850
5851 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005852 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005853 return -EINVAL;
5854 }
5855
5856 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005857 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005858 return -EINVAL;
5859 }
5860 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005861 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862
5863 if (control == WLAN_START_OFFLOADED_PACKETS)
5864 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005865 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005866 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005867
5868 hdd_err("Invalid control: %d", control);
5869
5870 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005871}
5872
5873/*
5874 * done with short names for the global vendor params
5875 * used by __wlan_hdd_cfg80211_offloaded_packets()
5876 */
5877#undef PARAM_MAX
5878#undef PARAM_REQUEST_ID
5879#undef PARAM_CONTROL
5880#undef PARAM_IP_PACKET
5881#undef PARAM_SRC_MAC_ADDR
5882#undef PARAM_DST_MAC_ADDR
5883#undef PARAM_PERIOD
5884
5885/**
5886 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5887 * @wiphy: wiphy structure pointer
5888 * @wdev: Wireless device structure pointer
5889 * @data: Pointer to the data received
5890 * @data_len: Length of @data
5891 *
5892 * Return: 0 on success; errno on failure
5893 */
5894static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5895 struct wireless_dev *wdev,
5896 const void *data,
5897 int data_len)
5898{
5899 int ret = 0;
5900
5901 cds_ssr_protect(__func__);
5902 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5903 wdev, data, data_len);
5904 cds_ssr_unprotect(__func__);
5905
5906 return ret;
5907}
5908#endif
5909
5910/*
5911 * define short names for the global vendor params
5912 * used by __wlan_hdd_cfg80211_monitor_rssi()
5913 */
5914#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5915#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5916#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5917#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5918#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5919
5920/**
5921 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5922 * @wiphy: Pointer to wireless phy
5923 * @wdev: Pointer to wireless device
5924 * @data: Pointer to data
5925 * @data_len: Data length
5926 *
5927 * Return: 0 on success, negative errno on failure
5928 */
5929static int
5930__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5931 struct wireless_dev *wdev,
5932 const void *data,
5933 int data_len)
5934{
5935 struct net_device *dev = wdev->netdev;
5936 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5937 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5938 struct nlattr *tb[PARAM_MAX + 1];
5939 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305940 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005941 int ret;
5942 uint32_t control;
5943 static const struct nla_policy policy[PARAM_MAX + 1] = {
5944 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5945 [PARAM_CONTROL] = { .type = NLA_U32 },
5946 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5947 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5948 };
5949
Jeff Johnson1f61b612016-02-12 16:28:33 -08005950 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005951
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305952 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5953 hdd_err("invalid session id: %d", adapter->sessionId);
5954 return -EINVAL;
5955 }
5956
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005957 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305958 if (ret)
5959 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005960
5961 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005962 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005963 return -ENOTSUPP;
5964 }
5965
5966 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005967 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005968 return -EINVAL;
5969 }
5970
5971 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005972 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005973 return -EINVAL;
5974 }
5975
5976 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005977 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005978 return -EINVAL;
5979 }
5980
5981 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5982 req.session_id = adapter->sessionId;
5983 control = nla_get_u32(tb[PARAM_CONTROL]);
5984
5985 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5986 req.control = true;
5987 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005988 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005989 return -EINVAL;
5990 }
5991
5992 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005993 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005994 return -EINVAL;
5995 }
5996
5997 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5998 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5999
6000 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006001 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006002 req.min_rssi, req.max_rssi);
6003 return -EINVAL;
6004 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006005 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006006 req.min_rssi, req.max_rssi);
6007
6008 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
6009 req.control = false;
6010 else {
Jeff Johnson77848112016-06-29 14:52:06 -07006011 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006012 return -EINVAL;
6013 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006014 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015 req.request_id, req.session_id, req.control);
6016
6017 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306018 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006019 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006020 return -EINVAL;
6021 }
6022
6023 return 0;
6024}
6025
6026/*
6027 * done with short names for the global vendor params
6028 * used by __wlan_hdd_cfg80211_monitor_rssi()
6029 */
6030#undef PARAM_MAX
6031#undef PARAM_CONTROL
6032#undef PARAM_REQUEST_ID
6033#undef PARAM_MAX_RSSI
6034#undef PARAM_MIN_RSSI
6035
6036/**
6037 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
6038 * @wiphy: wiphy structure pointer
6039 * @wdev: Wireless device structure pointer
6040 * @data: Pointer to the data received
6041 * @data_len: Length of @data
6042 *
6043 * Return: 0 on success; errno on failure
6044 */
6045static int
6046wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
6047 const void *data, int data_len)
6048{
6049 int ret;
6050
6051 cds_ssr_protect(__func__);
6052 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
6053 cds_ssr_unprotect(__func__);
6054
6055 return ret;
6056}
6057
6058/**
6059 * hdd_rssi_threshold_breached() - rssi breached NL event
6060 * @hddctx: HDD context
6061 * @data: rssi breached event data
6062 *
6063 * This function reads the rssi breached event %data and fill in the skb with
6064 * NL attributes and send up the NL event.
6065 *
6066 * Return: none
6067 */
6068void hdd_rssi_threshold_breached(void *hddctx,
6069 struct rssi_breach_event *data)
6070{
6071 hdd_context_t *hdd_ctx = hddctx;
6072 struct sk_buff *skb;
6073
6074 ENTER();
6075
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306076 if (wlan_hdd_validate_context(hdd_ctx))
6077 return;
6078 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006079 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006080 return;
6081 }
6082
6083 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
6084 NULL,
6085 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
6086 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
6087 GFP_KERNEL);
6088
6089 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006090 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006091 return;
6092 }
6093
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006094 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006096 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006097 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
6098
6099 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
6100 data->request_id) ||
6101 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
6102 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
6103 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
6104 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006105 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006106 goto fail;
6107 }
6108
6109 cfg80211_vendor_event(skb, GFP_KERNEL);
6110 return;
6111
6112fail:
6113 kfree_skb(skb);
6114 return;
6115}
6116
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306117static const struct nla_policy
6118ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
6119 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
6120};
6121
6122/**
6123 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
6124 * @wiphy: Pointer to wireless phy
6125 * @wdev: Pointer to wireless device
6126 * @data: Pointer to data
6127 * @data_len: Length of @data
6128 *
6129 * Return: 0 on success, negative errno on failure
6130 */
6131static int
6132__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
6133 struct wireless_dev *wdev,
6134 const void *data, int data_len)
6135{
6136 int status;
6137 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
6138 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07006139 struct net_device *dev = wdev->netdev;
6140 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306141
6142 ENTER_DEV(wdev->netdev);
6143
6144 status = wlan_hdd_validate_context(pHddCtx);
6145 if (0 != status)
6146 return status;
6147 if (!pHddCtx->config->fhostNSOffload) {
6148 hdd_err("ND Offload not supported");
6149 return -EINVAL;
6150 }
6151
6152 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
6153 (struct nlattr *)data,
6154 data_len, ns_offload_set_policy)) {
6155 hdd_err("nla_parse failed");
6156 return -EINVAL;
6157 }
6158
6159 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
6160 hdd_err("ND Offload flag attribute not present");
6161 return -EINVAL;
6162 }
6163
6164 pHddCtx->ns_offload_enable =
6165 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
6166
Dustin Brownd8279d22016-09-07 14:52:57 -07006167 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05306168 if (pHddCtx->ns_offload_enable)
6169 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
6170 else
6171 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07006172
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306173 return 0;
6174}
6175
6176/**
6177 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
6178 * @wiphy: pointer to wireless wiphy structure.
6179 * @wdev: pointer to wireless_dev structure.
6180 * @data: Pointer to the data to be passed via vendor interface
6181 * @data_len:Length of the data to be passed
6182 *
6183 * Return: Return the Success or Failure code.
6184 */
6185static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
6186 struct wireless_dev *wdev,
6187 const void *data, int data_len)
6188{
6189 int ret;
6190
6191 cds_ssr_protect(__func__);
6192 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
6193 cds_ssr_unprotect(__func__);
6194
6195 return ret;
6196}
6197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006198/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
6199 * @wiphy: Pointer to wireless phy
6200 * @wdev: Pointer to wireless device
6201 * @data: Pointer to data
6202 * @data_len: Data length
6203 *
6204 * This function return the preferred frequency list generated by the policy
6205 * manager.
6206 *
6207 * Return: success or failure code
6208 */
6209static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6210 struct wireless_dev
6211 *wdev, const void *data,
6212 int data_len)
6213{
6214 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6215 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306216 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306217 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006218 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306219 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006220 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006221 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6222 struct sk_buff *reply_skb;
6223
Jeff Johnson1f61b612016-02-12 16:28:33 -08006224 ENTER_DEV(wdev->netdev);
6225
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006226 ret = wlan_hdd_validate_context(hdd_ctx);
6227 if (ret)
6228 return -EINVAL;
6229
6230 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
6231 data, data_len, NULL)) {
6232 hdd_err("Invalid ATTR");
6233 return -EINVAL;
6234 }
6235
6236 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
6237 hdd_err("attr interface type failed");
6238 return -EINVAL;
6239 }
6240
6241 intf_mode = nla_get_u32(tb
6242 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
6243
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006244 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006245 hdd_err("Invalid interface type");
6246 return -EINVAL;
6247 }
6248
6249 hdd_debug("Userspace requested pref freq list");
6250
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006251 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
6252 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05306253 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306254 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006255 hdd_err("Get pcl failed");
6256 return -EINVAL;
6257 }
6258
6259 /* convert channel number to frequency */
6260 for (i = 0; i < pcl_len; i++) {
6261 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
6262 freq_list[i] =
6263 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006264 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006265 else
6266 freq_list[i] =
6267 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006268 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006269 }
6270
6271 /* send the freq_list back to supplicant */
6272 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
6273 sizeof(u32) *
6274 pcl_len +
6275 NLMSG_HDRLEN);
6276
6277 if (!reply_skb) {
6278 hdd_err("Allocate reply_skb failed");
6279 return -EINVAL;
6280 }
6281
6282 if (nla_put_u32(reply_skb,
6283 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
6284 intf_mode) ||
6285 nla_put(reply_skb,
6286 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
6287 sizeof(uint32_t) * pcl_len,
6288 freq_list)) {
6289 hdd_err("nla put fail");
6290 kfree_skb(reply_skb);
6291 return -EINVAL;
6292 }
6293
6294 return cfg80211_vendor_cmd_reply(reply_skb);
6295}
6296
6297/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
6298 * @wiphy: Pointer to wireless phy
6299 * @wdev: Pointer to wireless device
6300 * @data: Pointer to data
6301 * @data_len: Data length
6302 *
6303 * This function return the preferred frequency list generated by the policy
6304 * manager.
6305 *
6306 * Return: success or failure code
6307 */
6308static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6309 struct wireless_dev
6310 *wdev, const void *data,
6311 int data_len)
6312{
6313 int ret = 0;
6314
6315 cds_ssr_protect(__func__);
6316 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
6317 data, data_len);
6318 cds_ssr_unprotect(__func__);
6319
6320 return ret;
6321}
6322
6323/**
6324 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
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_probable_oper_channel(struct wiphy *wiphy,
6333 struct wireless_dev *wdev,
6334 const void *data,
6335 int data_len)
6336{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05306337 struct net_device *ndev = wdev->netdev;
6338 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006339 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6340 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006341 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006342 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6343 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006344
Jeff Johnson1f61b612016-02-12 16:28:33 -08006345 ENTER_DEV(ndev);
6346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006347 ret = wlan_hdd_validate_context(hdd_ctx);
6348 if (ret)
6349 return ret;
6350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006351 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
6352 data, data_len, NULL)) {
6353 hdd_err("Invalid ATTR");
6354 return -EINVAL;
6355 }
6356
6357 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
6358 hdd_err("attr interface type failed");
6359 return -EINVAL;
6360 }
6361
6362 intf_mode = nla_get_u32(tb
6363 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
6364
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006365 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006366 hdd_err("Invalid interface type");
6367 return -EINVAL;
6368 }
6369
6370 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
6371 hdd_err("attr probable freq failed");
6372 return -EINVAL;
6373 }
6374
6375 channel_hint = cds_freq_to_chan(nla_get_u32(tb
6376 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
6377
6378 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006379 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006380 channel_hint, HW_MODE_20_MHZ)) {
6381 hdd_err("Set channel hint failed due to concurrency check");
6382 return -EINVAL;
6383 }
6384
Krunal Soni09e55032016-06-07 10:06:55 -07006385 if (0 != wlan_hdd_check_remain_on_channel(adapter))
6386 hdd_warn("Remain On Channel Pending");
6387
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006388 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006389 if (!QDF_IS_STATUS_SUCCESS(ret))
6390 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006391
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006392 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
6393 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07006394 SIR_UPDATE_REASON_SET_OPER_CHAN);
6395 if (QDF_STATUS_E_FAILURE == ret) {
6396 /* return in the failure case */
6397 hdd_err("ERROR: connections update failed!!");
6398 return -EINVAL;
6399 }
6400
6401 if (QDF_STATUS_SUCCESS == ret) {
6402 /*
6403 * Success is the only case for which we expect hw mode
6404 * change to take place, hence we need to wait.
6405 * For any other return value it should be a pass
6406 * through
6407 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006408 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006409 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6410 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006411 return -EINVAL;
6412 }
6413
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006414 }
6415
6416 return 0;
6417}
6418
6419/**
6420 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6421 * @wiphy: Pointer to wireless phy
6422 * @wdev: Pointer to wireless device
6423 * @data: Pointer to data
6424 * @data_len: Data length
6425 *
6426 * Return: 0 on success, negative errno on failure
6427 */
6428static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6429 struct wireless_dev *wdev,
6430 const void *data,
6431 int data_len)
6432{
6433 int ret = 0;
6434
6435 cds_ssr_protect(__func__);
6436 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6437 data, data_len);
6438 cds_ssr_unprotect(__func__);
6439
6440 return ret;
6441}
6442
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306443static const struct
6444nla_policy
6445qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6446 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6447};
6448
6449/**
6450 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6451 * @wiphy: WIPHY structure pointer
6452 * @wdev: Wireless device structure pointer
6453 * @data: Pointer to the data received
6454 * @data_len: Length of the data received
6455 *
6456 * This function is used to get link properties like nss, rate flags and
6457 * operating frequency for the active connection with the given peer.
6458 *
6459 * Return: 0 on success and errno on failure
6460 */
6461static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6462 struct wireless_dev *wdev,
6463 const void *data,
6464 int data_len)
6465{
6466 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6467 struct net_device *dev = wdev->netdev;
6468 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6469 hdd_station_ctx_t *hdd_sta_ctx;
6470 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306471 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306472 uint32_t sta_id;
6473 struct sk_buff *reply_skb;
6474 uint32_t rate_flags = 0;
6475 uint8_t nss;
6476 uint8_t final_rate_flags = 0;
6477 uint32_t freq;
6478
Jeff Johnson1f61b612016-02-12 16:28:33 -08006479 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306480
Anurag Chouhan6d760662016-02-20 16:05:43 +05306481 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306482 hdd_err("Command not allowed in FTM mode");
6483 return -EPERM;
6484 }
6485
6486 if (0 != wlan_hdd_validate_context(hdd_ctx))
6487 return -EINVAL;
6488
6489 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6490 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006491 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306492 return -EINVAL;
6493 }
6494
6495 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006496 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306497 adapter->device_mode);
6498 return -EINVAL;
6499 }
6500
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306501 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306502 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006503 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306504 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6505
Krunal Sonib4326f22016-03-10 13:05:51 -08006506 if (adapter->device_mode == QDF_STA_MODE ||
6507 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306508 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6509 if ((hdd_sta_ctx->conn_info.connState !=
6510 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306511 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306512 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006513 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306514 MAC_ADDR_ARRAY(peer_mac));
6515 return -EINVAL;
6516 }
6517
6518 nss = hdd_sta_ctx->conn_info.nss;
6519 freq = cds_chan_to_freq(
6520 hdd_sta_ctx->conn_info.operationChannel);
6521 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006522 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6523 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306524
6525 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6526 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306527 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306528 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306529 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306530 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306531 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306532 break;
6533 }
6534
6535 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006536 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306537 MAC_ADDR_ARRAY(peer_mac));
6538 return -EINVAL;
6539 }
6540
6541 nss = adapter->aStaInfo[sta_id].nss;
6542 freq = cds_chan_to_freq(
6543 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6544 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6545 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006546 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306547 MAC_ADDR_ARRAY(peer_mac));
6548 return -EINVAL;
6549 }
6550
6551 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6552 if (rate_flags & eHAL_TX_RATE_VHT80) {
6553 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006554#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306555 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006556#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306557 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6558 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006559#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306560 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006561#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306562 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6563 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6564 } else if (rate_flags &
6565 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6566 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006567#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306568 if (rate_flags & eHAL_TX_RATE_HT40)
6569 final_rate_flags |=
6570 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006571#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306572 }
6573
6574 if (rate_flags & eHAL_TX_RATE_SGI) {
6575 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6576 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6577 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6578 }
6579 }
6580
6581 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6582 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6583
6584 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006585 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306586 return -EINVAL;
6587 }
6588
6589 if (nla_put_u8(reply_skb,
6590 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6591 nss) ||
6592 nla_put_u8(reply_skb,
6593 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6594 final_rate_flags) ||
6595 nla_put_u32(reply_skb,
6596 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6597 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006598 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306599 kfree_skb(reply_skb);
6600 return -EINVAL;
6601 }
6602
6603 return cfg80211_vendor_cmd_reply(reply_skb);
6604}
6605
6606/**
6607 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6608 * properties.
6609 * @wiphy: WIPHY structure pointer
6610 * @wdev: Wireless device structure pointer
6611 * @data: Pointer to the data received
6612 * @data_len: Length of the data received
6613 *
6614 * This function is used to get link properties like nss, rate flags and
6615 * operating frequency for the active connection with the given peer.
6616 *
6617 * Return: 0 on success and errno on failure
6618 */
6619static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6620 struct wireless_dev *wdev,
6621 const void *data,
6622 int data_len)
6623{
6624 int ret = 0;
6625
6626 cds_ssr_protect(__func__);
6627 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6628 wdev, data, data_len);
6629 cds_ssr_unprotect(__func__);
6630
6631 return ret;
6632}
6633
Peng Xu278d0122015-09-24 16:34:17 -07006634static const struct
6635nla_policy
6636qca_wlan_vendor_ota_test_policy
6637[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6638 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6639};
6640
6641/**
6642 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6643 * @wiphy: Pointer to wireless phy
6644 * @wdev: Pointer to wireless device
6645 * @data: Pointer to data
6646 * @data_len: Data length
6647 *
6648 * Return: 0 on success, negative errno on failure
6649 */
6650static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6651 struct wireless_dev *wdev,
6652 const void *data,
6653 int data_len)
6654{
6655 struct net_device *dev = wdev->netdev;
6656 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6657 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6658 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6659 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6660 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306661 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006662 uint32_t current_roam_state;
6663
Jeff Johnson1f61b612016-02-12 16:28:33 -08006664 ENTER_DEV(dev);
6665
Anurag Chouhan6d760662016-02-20 16:05:43 +05306666 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006667 hdd_err("Command not allowed in FTM mode");
6668 return -EPERM;
6669 }
6670
6671 if (0 != wlan_hdd_validate_context(hdd_ctx))
6672 return -EINVAL;
6673
6674 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6675 data, data_len,
6676 qca_wlan_vendor_ota_test_policy)) {
6677 hdd_err("invalid attr");
6678 return -EINVAL;
6679 }
6680
6681 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6682 hdd_err("attr ota test failed");
6683 return -EINVAL;
6684 }
6685
6686 ota_enable = nla_get_u8(
6687 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6688
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006689 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006690 if (ota_enable != 1) {
6691 hdd_err("Invalid value, only enable test mode is supported!");
6692 return -EINVAL;
6693 }
6694
6695 current_roam_state =
6696 sme_get_current_roam_state(hal, adapter->sessionId);
6697 status = sme_stop_roaming(hal, adapter->sessionId,
6698 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306699 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006700 hdd_err("Enable/Disable roaming failed");
6701 return -EINVAL;
6702 }
6703
6704 status = sme_ps_enable_disable(hal, adapter->sessionId,
6705 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306706 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006707 hdd_err("Enable/Disable power save failed");
6708 /* restore previous roaming setting */
6709 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6710 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6711 status = sme_start_roaming(hal, adapter->sessionId,
6712 eCsrHddIssued);
6713 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6714 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6715 status = sme_stop_roaming(hal, adapter->sessionId,
6716 eCsrHddIssued);
6717
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306718 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006719 hdd_err("Restoring roaming state failed");
6720
6721 return -EINVAL;
6722 }
6723
6724
6725 return 0;
6726}
6727
6728/**
6729 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6730 * @wiphy: Pointer to wireless phy
6731 * @wdev: Pointer to wireless device
6732 * @data: Pointer to data
6733 * @data_len: Data length
6734 *
6735 * Return: 0 on success, negative errno on failure
6736 */
6737static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6738 struct wireless_dev *wdev,
6739 const void *data,
6740 int data_len)
6741{
6742 int ret = 0;
6743
6744 cds_ssr_protect(__func__);
6745 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6746 cds_ssr_unprotect(__func__);
6747
6748 return ret;
6749}
6750
Peng Xu4d67c8f2015-10-16 16:02:26 -07006751/**
6752 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6753 * @wiphy: Pointer to wireless phy
6754 * @wdev: Pointer to wireless device
6755 * @data: Pointer to data
6756 * @data_len: Data length
6757 *
6758 * Return: 0 on success, negative errno on failure
6759 */
6760static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6761 struct wireless_dev *wdev,
6762 const void *data,
6763 int data_len)
6764{
6765 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6766 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006767 hdd_adapter_t *adapter;
6768 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006769 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6770 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006771 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006772
Jeff Johnson1f61b612016-02-12 16:28:33 -08006773 ENTER_DEV(dev);
6774
Peng Xu4d67c8f2015-10-16 16:02:26 -07006775 ret = wlan_hdd_validate_context(hdd_ctx);
6776 if (ret)
6777 return ret;
6778
6779 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6780
6781 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6782 data, data_len, NULL)) {
6783 hdd_err("Invalid ATTR");
6784 return -EINVAL;
6785 }
6786
6787 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6788 hdd_err("attr tx power scale failed");
6789 return -EINVAL;
6790 }
6791
6792 scale_value = nla_get_u8(tb
6793 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6794
6795 if (scale_value > MAX_TXPOWER_SCALE) {
6796 hdd_err("Invalid tx power scale level");
6797 return -EINVAL;
6798 }
6799
Peng Xu62c8c432016-05-09 15:23:02 -07006800 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006801
Peng Xu62c8c432016-05-09 15:23:02 -07006802 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006803 hdd_err("Set tx power scale failed");
6804 return -EINVAL;
6805 }
6806
6807 return 0;
6808}
6809
6810/**
6811 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6812 * @wiphy: Pointer to wireless phy
6813 * @wdev: Pointer to wireless device
6814 * @data: Pointer to data
6815 * @data_len: Data length
6816 *
6817 * Return: 0 on success, negative errno on failure
6818 */
6819static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6820 struct wireless_dev *wdev,
6821 const void *data,
6822 int data_len)
6823{
Peng Xu62c8c432016-05-09 15:23:02 -07006824 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006825
6826 cds_ssr_protect(__func__);
6827 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6828 data, data_len);
6829 cds_ssr_unprotect(__func__);
6830
6831 return ret;
6832}
6833
6834/**
6835 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6836 * @wiphy: Pointer to wireless phy
6837 * @wdev: Pointer to wireless device
6838 * @data: Pointer to data
6839 * @data_len: Data length
6840 *
6841 * Return: 0 on success, negative errno on failure
6842 */
6843static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6844 struct wireless_dev *wdev,
6845 const void *data,
6846 int data_len)
6847{
6848 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6849 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006850 hdd_adapter_t *adapter;
6851 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006852 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6853 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006854 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006855
Jeff Johnson1f61b612016-02-12 16:28:33 -08006856 ENTER_DEV(dev);
6857
Peng Xu4d67c8f2015-10-16 16:02:26 -07006858 ret = wlan_hdd_validate_context(hdd_ctx);
6859 if (ret)
6860 return ret;
6861
6862 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6863
6864 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6865 data, data_len, NULL)) {
6866 hdd_err("Invalid ATTR");
6867 return -EINVAL;
6868 }
6869
6870 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6871 hdd_err("attr tx power decrease db value failed");
6872 return -EINVAL;
6873 }
6874
6875 scale_value = nla_get_u8(tb
6876 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6877
Peng Xu62c8c432016-05-09 15:23:02 -07006878 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6879 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006880
Peng Xu62c8c432016-05-09 15:23:02 -07006881 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006882 hdd_err("Set tx power decrease db failed");
6883 return -EINVAL;
6884 }
6885
6886 return 0;
6887}
6888
6889/**
6890 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6891 * @wiphy: Pointer to wireless phy
6892 * @wdev: Pointer to wireless device
6893 * @data: Pointer to data
6894 * @data_len: Data length
6895 *
6896 * Return: 0 on success, negative errno on failure
6897 */
6898static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6899 struct wireless_dev *wdev,
6900 const void *data,
6901 int data_len)
6902{
Peng Xu62c8c432016-05-09 15:23:02 -07006903 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006904
6905 cds_ssr_protect(__func__);
6906 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6907 data, data_len);
6908 cds_ssr_unprotect(__func__);
6909
6910 return ret;
6911}
Peng Xu8fdaa492016-06-22 10:20:47 -07006912
6913/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306914 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6915 * @wiphy: Pointer to wireless phy
6916 * @wdev: Pointer to wireless device
6917 * @data: Pointer to data
6918 * @data_len: Data length
6919 *
6920 * Processes the conditional channel switch request and invokes the helper
6921 * APIs to process the channel switch request.
6922 *
6923 * Return: 0 on success, negative errno on failure
6924 */
6925static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6926 struct wireless_dev *wdev,
6927 const void *data,
6928 int data_len)
6929{
6930 int ret;
6931 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6932 struct net_device *dev = wdev->netdev;
6933 hdd_adapter_t *adapter;
6934 struct nlattr
6935 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6936 uint32_t freq_len, i;
6937 uint32_t *freq;
6938 uint8_t chans[QDF_MAX_NUM_CHAN];
6939
6940 ENTER_DEV(dev);
6941
6942 ret = wlan_hdd_validate_context(hdd_ctx);
6943 if (ret)
6944 return ret;
6945
6946 if (!hdd_ctx->config->enableDFSMasterCap) {
6947 hdd_err("DFS master capability is not present in the driver");
6948 return -EINVAL;
6949 }
6950
6951 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6952 hdd_err("Command not allowed in FTM mode");
6953 return -EPERM;
6954 }
6955
6956 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6957 if (adapter->device_mode != QDF_SAP_MODE) {
6958 hdd_err("Invalid device mode %d", adapter->device_mode);
6959 return -EINVAL;
6960 }
6961
6962 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6963 data, data_len, NULL)) {
6964 hdd_err("Invalid ATTR");
6965 return -EINVAL;
6966 }
6967
6968 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6969 hdd_err("Frequency list is missing");
6970 return -EINVAL;
6971 }
6972
6973 freq_len = nla_len(
6974 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6975 sizeof(uint32_t);
6976
6977 if (freq_len > QDF_MAX_NUM_CHAN) {
6978 hdd_err("insufficient space to hold channels");
6979 return -ENOMEM;
6980 }
6981
6982 hdd_debug("freq_len=%d", freq_len);
6983
6984 freq = nla_data(
6985 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6986
6987
6988 for (i = 0; i < freq_len; i++) {
6989 if (freq[i] == 0)
6990 chans[i] = 0;
6991 else
6992 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6993
6994 hdd_debug("freq[%d]=%d", i, freq[i]);
6995 }
6996
6997 /*
6998 * The input frequency list from user space is designed to be a
6999 * priority based frequency list. This is only to accommodate any
7000 * future request. But, current requirement is only to perform CAC
7001 * on a single channel. So, the first entry from the list is picked.
7002 *
7003 * If channel is zero, any channel in the available outdoor regulatory
7004 * domain will be selected.
7005 */
7006 ret = wlan_hdd_request_pre_cac(chans[0]);
7007 if (ret) {
7008 hdd_err("pre cac request failed with reason:%d", ret);
7009 return ret;
7010 }
7011
7012 return 0;
7013}
7014
7015/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007016 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
7017 * @wiphy: Pointer to wireless phy
7018 * @wdev: Pointer to wireless device
7019 * @data: Pointer to data
7020 * @data_len: Data length
7021 *
7022 * This function is to process the p2p listen offload start vendor
7023 * command. It parses the input parameters and invoke WMA API to
7024 * send the command to firmware.
7025 *
7026 * Return: 0 on success, negative errno on failure
7027 */
7028static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
7029 struct wireless_dev *wdev,
7030 const void *data,
7031 int data_len)
7032{
7033 int ret;
7034 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7035 struct net_device *dev = wdev->netdev;
7036 hdd_adapter_t *adapter;
7037 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
7038 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07007039
7040 ENTER_DEV(dev);
7041
7042 ret = wlan_hdd_validate_context(hdd_ctx);
7043 if (ret)
7044 return ret;
7045
7046 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7047 hdd_err("Command not allowed in FTM mode");
7048 return -EPERM;
7049 }
7050
7051 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7052 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
7053 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
7054 (adapter->device_mode != QDF_P2P_GO_MODE)) {
7055 hdd_err("Invalid device mode %d", adapter->device_mode);
7056 return -EINVAL;
7057 }
7058
7059 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
7060 data, data_len, NULL)) {
7061 hdd_err("Invalid ATTR");
7062 return -EINVAL;
7063 }
7064
7065 memset(&params, 0, sizeof(params));
7066
7067 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
7068 params.ctl_flags = 1; /* set to default value */
7069 else
7070 params.ctl_flags = nla_get_u32(tb
7071 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
7072
7073 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
7074 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
7075 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
7076 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
7077 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
7078 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
7079 hdd_err("Attribute parsing failed");
7080 return -EINVAL;
7081 }
7082
7083 params.vdev_id = adapter->sessionId;
7084 params.freq = nla_get_u32(tb
7085 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
7086 if ((params.freq != 2412) && (params.freq != 2437) &&
7087 (params.freq != 2462)) {
7088 hdd_err("Invalid listening channel: %d", params.freq);
7089 return -EINVAL;
7090 }
7091
7092 params.period = nla_get_u32(tb
7093 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
7094 if (!((params.period > 0) && (params.period < UINT_MAX))) {
7095 hdd_err("Invalid period: %d", params.period);
7096 return -EINVAL;
7097 }
7098
7099 params.interval = nla_get_u32(tb
7100 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
7101 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
7102 hdd_err("Invalid interval: %d", params.interval);
7103 return -EINVAL;
7104 }
7105
7106 params.count = nla_get_u32(tb
7107 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08007108 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07007109 hdd_err("Invalid count: %d", params.count);
7110 return -EINVAL;
7111 }
7112
7113 params.device_types = nla_data(tb
7114 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
7115 if (params.device_types == NULL) {
7116 hdd_err("Invalid device types");
7117 return -EINVAL;
7118 }
7119
7120 params.dev_types_len = nla_len(tb
7121 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
7122 if (params.dev_types_len < 8) {
7123 hdd_err("Invalid device type length: %d", params.dev_types_len);
7124 return -EINVAL;
7125 }
7126
7127 params.probe_resp_tmplt = nla_data(tb
7128 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
7129 if (params.probe_resp_tmplt == NULL) {
7130 hdd_err("Invalid probe response template");
7131 return -EINVAL;
7132 }
7133
7134 params.probe_resp_len = nla_len(tb
7135 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
7136 if (params.probe_resp_len == 0) {
7137 hdd_err("Invalid probe resp template length: %d",
7138 params.probe_resp_len);
7139 return -EINVAL;
7140 }
7141
7142 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
7143 params.freq, params.period, params.interval, params.count);
7144
Wu Gao9a704f42017-03-10 18:42:11 +08007145 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07007146}
7147
7148
7149/**
7150 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
7151 * @wiphy: Pointer to wireless phy
7152 * @wdev: Pointer to wireless device
7153 * @data: Pointer to data
7154 * @data_len: Data length
7155 *
7156 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
7157 * to process p2p listen offload start vendor command.
7158 *
7159 * Return: 0 on success, negative errno on failure
7160 */
7161static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
7162 struct wireless_dev *wdev,
7163 const void *data,
7164 int data_len)
7165{
7166 int ret = 0;
7167
7168 cds_ssr_protect(__func__);
7169 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
7170 data, data_len);
7171 cds_ssr_unprotect(__func__);
7172
7173 return ret;
7174}
7175
7176/**
7177 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7178 * @wiphy: Pointer to wireless phy
7179 * @wdev: Pointer to wireless device
7180 * @data: Pointer to data
7181 * @data_len: Data length
7182 *
7183 * This function is to process the p2p listen offload stop vendor
7184 * command. It invokes WMA API to send command to firmware.
7185 *
7186 * Return: 0 on success, negative errno on failure
7187 */
7188static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7189 struct wireless_dev *wdev,
7190 const void *data,
7191 int data_len)
7192{
Peng Xu8fdaa492016-06-22 10:20:47 -07007193 hdd_adapter_t *adapter;
7194 struct net_device *dev = wdev->netdev;
7195
7196 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7197 hdd_err("Command not allowed in FTM mode");
7198 return -EPERM;
7199 }
7200
7201 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7202 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
7203 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
7204 (adapter->device_mode != QDF_P2P_GO_MODE)) {
7205 hdd_err("Invalid device mode");
7206 return -EINVAL;
7207 }
7208
Wu Gao9a704f42017-03-10 18:42:11 +08007209 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07007210}
7211
7212/**
7213 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7214 * @wiphy: Pointer to wireless phy
7215 * @wdev: Pointer to wireless device
7216 * @data: Pointer to data
7217 * @data_len: Data length
7218 *
7219 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
7220 * to process p2p listen offload stop vendor command.
7221 *
7222 * Return: 0 on success, negative errno on failure
7223 */
7224static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7225 struct wireless_dev *wdev,
7226 const void *data,
7227 int data_len)
7228{
7229 int ret = 0;
7230
7231 cds_ssr_protect(__func__);
7232 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
7233 data, data_len);
7234 cds_ssr_unprotect(__func__);
7235
7236 return ret;
7237}
7238
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307239/**
7240 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
7241 * @wiphy: Pointer to wireless phy
7242 * @wdev: Pointer to wireless device
7243 * @data: Pointer to data
7244 * @data_len: Data length
7245 *
7246 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
7247 * to process the conditional channel switch request.
7248 *
7249 * Return: 0 on success, negative errno on failure
7250 */
7251static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
7252 struct wireless_dev *wdev,
7253 const void *data,
7254 int data_len)
7255{
7256 int ret;
7257
7258 cds_ssr_protect(__func__);
7259 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
7260 data, data_len);
7261 cds_ssr_unprotect(__func__);
7262
7263 return ret;
7264}
7265
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307266/*
7267 * define short names for the global vendor params
7268 * used by __wlan_hdd_cfg80211_bpf_offload()
7269 */
7270#define BPF_INVALID \
7271 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
7272#define BPF_SET_RESET \
7273 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
7274#define BPF_VERSION \
7275 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
7276#define BPF_FILTER_ID \
7277 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
7278#define BPF_PACKET_SIZE \
7279 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
7280#define BPF_CURRENT_OFFSET \
7281 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
7282#define BPF_PROGRAM \
7283 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
7284#define BPF_MAX \
7285 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07007286
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307287static const struct nla_policy
7288wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
7289 [BPF_SET_RESET] = {.type = NLA_U32},
7290 [BPF_VERSION] = {.type = NLA_U32},
7291 [BPF_FILTER_ID] = {.type = NLA_U32},
7292 [BPF_PACKET_SIZE] = {.type = NLA_U32},
7293 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
7294 [BPF_PROGRAM] = {.type = NLA_U8},
7295};
7296
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007297struct bpf_offload_priv {
7298 struct sir_bpf_get_offload bpf_get_offload;
7299};
7300
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307301/**
7302 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007303 * @context: opaque context originally passed to SME. HDD always passes
7304 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307305 * @bpf_get_offload: struct for get offload
7306 *
7307 * This function receives the response/data from the lower layer and
7308 * checks to see if the thread is still waiting then post the results to
7309 * upper layer, if the request has timed out then ignore.
7310 *
7311 * Return: None
7312 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007313static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007314 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307315{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007316 struct hdd_request *request;
7317 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307318
7319 ENTER();
7320
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007321 request = hdd_request_get(context);
7322 if (!request) {
7323 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307324 return;
7325 }
7326
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007327 priv = hdd_request_priv(request);
7328 priv->bpf_get_offload = *data;
7329 hdd_request_complete(request);
7330 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307331}
7332
7333/**
7334 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
7335 * @hdd_context: hdd_context
7336 * @bpf_get_offload: struct for get offload
7337 *
7338 * Return: 0 on success, error number otherwise.
7339 */
7340static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
7341 struct sir_bpf_get_offload *bpf_get_offload)
7342{
7343 struct sk_buff *skb;
7344 uint32_t nl_buf_len;
7345
7346 ENTER();
7347
7348 nl_buf_len = NLMSG_HDRLEN;
7349 nl_buf_len +=
7350 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
7351 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
7352
7353 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7354 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007355 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307356 return -ENOMEM;
7357 }
7358
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007359 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307360 bpf_get_offload->bpf_version,
7361 bpf_get_offload->max_bytes_for_bpf_inst);
7362
7363 if (nla_put_u32(skb, BPF_PACKET_SIZE,
7364 bpf_get_offload->max_bytes_for_bpf_inst) ||
7365 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007366 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307367 goto nla_put_failure;
7368 }
7369
7370 cfg80211_vendor_cmd_reply(skb);
7371 EXIT();
7372 return 0;
7373
7374nla_put_failure:
7375 kfree_skb(skb);
7376 return -EINVAL;
7377}
7378
7379/**
7380 * hdd_get_bpf_offload - Get BPF offload Capabilities
7381 * @hdd_ctx: Hdd context
7382 *
7383 * Return: 0 on success, errno on failure
7384 */
7385static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
7386{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307387 QDF_STATUS status;
7388 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007389 void *cookie;
7390 struct hdd_request *request;
7391 struct bpf_offload_priv *priv;
7392 static const struct hdd_request_params params = {
7393 .priv_size = sizeof(*priv),
7394 .timeout_ms = WLAN_WAIT_TIME_BPF,
7395 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307396
7397 ENTER();
7398
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007399 request = hdd_request_alloc(&params);
7400 if (!request) {
7401 hdd_err("Unable to allocate request");
7402 return -EINVAL;
7403 }
7404 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307405
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007406 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7407 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007408 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307409 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007410 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007411 ret = qdf_status_to_os_return(status);
7412 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307413 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007414 ret = hdd_request_wait_for_response(request);
7415 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007416 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007417 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307418 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007419 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307420 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007421 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307422 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007423 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307424
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007425cleanup:
7426 /*
7427 * either we never sent a request to SME, we sent a request to
7428 * SME and timed out, or we sent a request to SME, received a
7429 * response from SME, and posted the response to userspace.
7430 * regardless we are done with the request.
7431 */
7432 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307433 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007434
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307435 return ret;
7436}
7437
7438/**
7439 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7440 * @hdd_ctx: Hdd context
7441 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307442 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307443 *
7444 * Return: 0 on success; errno on failure
7445 */
7446static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7447 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307448 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307449{
7450 struct sir_bpf_set_offload *bpf_set_offload;
7451 QDF_STATUS status;
7452 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307453 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307454
7455 ENTER();
7456
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307457 if (adapter->device_mode == QDF_STA_MODE ||
7458 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7459 if (!hdd_conn_is_connected(
7460 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7461 hdd_err("Not in Connected state!");
7462 return -ENOTSUPP;
7463 }
7464 }
7465
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307466 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7467 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007468 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307469 return -ENOMEM;
7470 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307471
7472 /* Parse and fetch bpf packet size */
7473 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007474 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307475 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307476 goto fail;
7477 }
7478 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7479
7480 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007481 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307482 goto post_sme;
7483 }
7484
7485 /* Parse and fetch bpf program */
7486 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007487 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307488 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307489 goto fail;
7490 }
7491
7492 prog_len = nla_len(tb[BPF_PROGRAM]);
7493 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307494
7495 if (bpf_set_offload->program == NULL) {
7496 hdd_err("qdf_mem_malloc failed for bpf offload program");
7497 ret = -ENOMEM;
7498 goto fail;
7499 }
7500
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307501 bpf_set_offload->current_length = prog_len;
7502 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307503 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307504
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007505 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007506 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307507 bpf_set_offload->program, prog_len);
7508
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307509 /* Parse and fetch filter Id */
7510 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007511 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307512 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307513 goto fail;
7514 }
7515 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7516
7517 /* Parse and fetch current offset */
7518 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007519 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307520 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307521 goto fail;
7522 }
7523 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7524
7525post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007526 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 +05307527 bpf_set_offload->session_id,
7528 bpf_set_offload->version,
7529 bpf_set_offload->filter_id,
7530 bpf_set_offload->total_length,
7531 bpf_set_offload->current_length,
7532 bpf_set_offload->current_offset);
7533
7534 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7535 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007536 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307537 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307538 goto fail;
7539 }
7540 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307541
7542fail:
7543 if (bpf_set_offload->current_length)
7544 qdf_mem_free(bpf_set_offload->program);
7545 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307546 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307547}
7548
7549/**
7550 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7551 * @wiphy: wiphy structure pointer
7552 * @wdev: Wireless device structure pointer
7553 * @data: Pointer to the data received
7554 * @data_len: Length of @data
7555 *
7556 * Return: 0 on success; errno on failure
7557 */
7558static int
7559__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7560 struct wireless_dev *wdev,
7561 const void *data, int data_len)
7562{
7563 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7564 struct net_device *dev = wdev->netdev;
7565 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7566 struct nlattr *tb[BPF_MAX + 1];
7567 int ret_val, packet_filter_subcmd;
7568
7569 ENTER();
7570
7571 ret_val = wlan_hdd_validate_context(hdd_ctx);
7572 if (ret_val)
7573 return ret_val;
7574
7575 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007576 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307577 return -EINVAL;
7578 }
7579
7580 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007581 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307582 return -ENOTSUPP;
7583 }
7584
7585 if (nla_parse(tb, BPF_MAX, data, data_len,
7586 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007587 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307588 return -EINVAL;
7589 }
7590
7591 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007592 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307593 return -EINVAL;
7594 }
7595
7596 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7597
7598 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7599 return hdd_get_bpf_offload(hdd_ctx);
7600 else
7601 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307602 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307603}
7604
7605/**
7606 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7607 * @wiphy: wiphy structure pointer
7608 * @wdev: Wireless device structure pointer
7609 * @data: Pointer to the data received
7610 * @data_len: Length of @data
7611 *
7612 * Return: 0 on success; errno on failure
7613 */
7614
7615static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7616 struct wireless_dev *wdev,
7617 const void *data, int data_len)
7618{
7619 int ret;
7620
7621 cds_ssr_protect(__func__);
7622 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7623 cds_ssr_unprotect(__func__);
7624
7625 return ret;
7626}
7627
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307628/**
7629 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7630 * @pre_cac_adapter: AP adapter used for pre cac
7631 * @status: Status (true or false)
7632 * @handle: Global handle
7633 *
7634 * Sets the status of pre cac i.e., whether the pre cac is active or not
7635 *
7636 * Return: Zero on success, non-zero on failure
7637 */
7638static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7639 bool status, tHalHandle handle)
7640{
7641 QDF_STATUS ret;
7642
7643 ret = wlan_sap_set_pre_cac_status(
7644 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7645 if (QDF_IS_STATUS_ERROR(ret))
7646 return -EINVAL;
7647
7648 return 0;
7649}
7650
7651/**
7652 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7653 * @ap_adapter: AP adapter
7654 * @chan_before_pre_cac: Channel
7655 *
7656 * Saves the channel which the AP was beaconing on before moving to the pre
7657 * cac channel. If radar is detected on the pre cac channel, this saved
7658 * channel will be used for AP operations.
7659 *
7660 * Return: Zero on success, non-zero on failure
7661 */
7662static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7663 uint8_t chan_before_pre_cac)
7664{
7665 QDF_STATUS ret;
7666
7667 ret = wlan_sap_set_chan_before_pre_cac(
7668 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7669 if (QDF_IS_STATUS_ERROR(ret))
7670 return -EINVAL;
7671
7672 return 0;
7673}
7674
7675/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307676 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7677 * are in nol list from provided channel list
7678 * @adapter: AP adapter
7679 * @channel_count: channel count
7680 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307681 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307682 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307683 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307684static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7685 uint32_t *channel_count,
7686 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307687{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307688 uint8_t i, j;
7689 uint32_t nol_len = 0;
7690 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7691 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7692 uint32_t chan_count;
7693 bool found;
7694 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307695
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307696 if (!hdd_ctx) {
7697 hdd_err("hdd ctx not found");
7698 *channel_count = 0;
7699 return;
7700 }
7701
7702 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7703 hdd_err("invalid channel count %d", *channel_count);
7704 return;
7705 }
7706
7707 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7708 if (nol_len == 0)
7709 return;
7710
7711 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7712 chan_count = *channel_count;
7713 qdf_mem_zero(channel_list, chan_count);
7714 *channel_count = 0;
7715
7716 for (i = 0 ; i < chan_count; i++) {
7717 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7718 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7719 continue;
7720 found = false;
7721 for (j = 0; j < nol_len; j++) {
7722 if (tmp_chan_list[i] == nol[j]) {
7723 found = true;
7724 hdd_notice("skipped channel %d due to nol",
7725 nol[j]);
7726 break;
7727 }
7728 }
7729 if (!found) {
7730 channel_list[*channel_count] = tmp_chan_list[i];
7731 *channel_count = *channel_count + 1;
7732 }
7733 }
7734}
7735
7736int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7737 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307738 uint8_t *channel_list,
7739 eCsrBand band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307740{
7741 tsap_Config_t *sap_config;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307742 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7743 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7744 uint32_t chan_count;
7745 uint8_t i;
7746 QDF_STATUS status;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307747
7748 sap_config = &adapter->sessionCtx.ap.sapConfig;
7749
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307750 status =
7751 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7752 tmp_chan_list,
7753 &chan_count);
7754 if (QDF_IS_STATUS_ERROR(status)) {
7755 hdd_err("Failed to get channel list");
7756 return -EINVAL;
7757 }
7758 for (i = 0; i < chan_count; i++) {
7759 if (*channel_count < QDF_MAX_NUM_CHAN) {
7760 if ((eCSR_BAND_24 == band) &&
7761 (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
7762 channel_list[*channel_count] = tmp_chan_list[i];
7763 *channel_count += 1;
7764 } else if ((eCSR_BAND_5G == band) &&
7765 (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
7766 channel_list[*channel_count] = tmp_chan_list[i];
7767 *channel_count += 1;
7768 }
7769 } else {
7770 break;
7771 }
7772 }
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307773 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307774 if (*channel_count == 0) {
7775 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307776 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307777 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307778
7779 return 0;
7780}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307781
7782/**
7783 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7784 * @hdd_ctx: HDD context
7785 * @ap_adapter: AP adapter
7786 * @channel: Channel requested by userspace
7787 * @pre_cac_chan: Pointer to the pre CAC channel
7788 *
7789 * Validates the channel provided by userspace. If user provided channel 0,
7790 * a valid outdoor channel must be selected from the regulatory channel.
7791 *
7792 * Return: Zero on success and non zero value on error
7793 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007794static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7795 hdd_adapter_t *ap_adapter,
7796 uint8_t channel,
7797 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307798{
7799 uint32_t i, j;
7800 QDF_STATUS status;
7801 int ret;
7802 uint8_t nol[QDF_MAX_NUM_CHAN];
7803 uint32_t nol_len = 0, weight_len = 0;
7804 bool found;
7805 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7806 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7807 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7808
7809 if (0 == channel) {
7810 /* Channel is not obtained from PCL because PCL may not have
7811 * the entire channel list. For example: if SAP is up on
7812 * channel 6 and PCL is queried for the next SAP interface,
7813 * if SCC is preferred, the PCL will contain only the channel
7814 * 6. But, we are in need of a DFS channel. So, going with the
7815 * first channel from the valid channel list.
7816 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007817 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7818 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307819 if (QDF_IS_STATUS_ERROR(status)) {
7820 hdd_err("Failed to get channel list");
7821 return -EINVAL;
7822 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007823 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307824 pcl_weights, weight_len);
7825 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7826 for (i = 0; i < len; i++) {
7827 found = false;
7828 for (j = 0; j < nol_len; j++) {
7829 if (channel_list[i] == nol[j]) {
7830 found = true;
7831 break;
7832 }
7833 }
7834 if (found)
7835 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007836 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7837 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307838 *pre_cac_chan = channel_list[i];
7839 break;
7840 }
7841 }
7842 if (*pre_cac_chan == 0) {
7843 hdd_err("unable to find outdoor channel");
7844 return -EINVAL;
7845 }
7846 } else {
7847 /* Only when driver selects a channel, check is done for
7848 * unnsafe and NOL channels. When user provides a fixed channel
7849 * the user is expected to take care of this.
7850 */
7851 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007852 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307853 hdd_err("Invalid channel for pre cac:%d", channel);
7854 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307855 }
Jeff Johnson68755312017-02-10 11:46:55 -08007856
7857 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307858 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007859 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307860 return 0;
7861}
7862
7863/**
7864 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7865 * @channel: Channel option provided by userspace
7866 *
7867 * Sets the driver to the required hardware mode and start an adapater for
7868 * pre CAC which will mimic an AP.
7869 *
7870 * Return: Zero on success, non-zero value on error
7871 */
7872int wlan_hdd_request_pre_cac(uint8_t channel)
7873{
Krunal Sonib37bb352016-12-20 14:12:21 -08007874 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307875 hdd_context_t *hdd_ctx;
7876 int ret;
7877 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7878 hdd_ap_ctx_t *hdd_ap_ctx;
7879 QDF_STATUS status;
7880 struct wiphy *wiphy;
7881 struct net_device *dev;
7882 struct cfg80211_chan_def chandef;
7883 enum nl80211_channel_type channel_type;
7884 uint32_t freq;
7885 struct ieee80211_channel *chan;
7886 tHalHandle handle;
7887 bool val;
7888
7889 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7890 if (0 != wlan_hdd_validate_context(hdd_ctx))
7891 return -EINVAL;
7892
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007893 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307894 hdd_err("pre cac not allowed in concurrency");
7895 return -EINVAL;
7896 }
7897
7898 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7899 if (!ap_adapter) {
7900 hdd_err("unable to get SAP adapter");
7901 return -EINVAL;
7902 }
7903
7904 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7905 if (!handle) {
7906 hdd_err("Invalid handle");
7907 return -EINVAL;
7908 }
7909
7910 val = wlan_sap_is_pre_cac_active(handle);
7911 if (val) {
7912 hdd_err("pre cac is already in progress");
7913 return -EINVAL;
7914 }
7915
7916 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7917 if (!hdd_ap_ctx) {
7918 hdd_err("SAP context is NULL");
7919 return -EINVAL;
7920 }
7921
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007922 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7923 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307924 hdd_err("SAP is already on DFS channel:%d",
7925 hdd_ap_ctx->operatingChannel);
7926 return -EINVAL;
7927 }
7928
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007929 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307930 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7931 hdd_ap_ctx->operatingChannel);
7932 return -EINVAL;
7933 }
7934
Krunal Sonib37bb352016-12-20 14:12:21 -08007935 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7936 if (!mac_addr) {
7937 hdd_err("can't add virtual intf: Not getting valid mac addr");
7938 return -EINVAL;
7939 }
7940
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007941 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307942
7943 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7944 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007945 if (ret != 0) {
7946 hdd_err("can't validate pre-cac channel");
7947 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307948 }
7949
7950 hdd_debug("starting pre cac SAP adapter");
7951
7952 /* Starting a SAP adapter:
7953 * Instead of opening an adapter, we could just do a SME open session
7954 * for AP type. But, start BSS would still need an adapter.
7955 * So, this option is not taken.
7956 *
7957 * hdd open adapter is going to register this precac interface with
7958 * user space. This interface though exposed to user space will be in
7959 * DOWN state. Consideration was done to avoid this registration to the
7960 * user space. But, as part of SAP operations multiple events are sent
7961 * to user space. Some of these events received from unregistered
7962 * interface was causing crashes. So, retaining the registration.
7963 *
7964 * So, this interface would remain registered and will remain in DOWN
7965 * state for the CAC duration. We will add notes in the feature
7966 * announcement to not use this temporary interface for any activity
7967 * from user space.
7968 */
7969 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007970 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307971 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307972 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007973 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307974 }
7975
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307976 /*
7977 * This interface is internally created by the driver. So, no interface
7978 * up comes for this interface from user space and hence starting
7979 * the adapter internally.
7980 */
7981 if (hdd_start_adapter(pre_cac_adapter)) {
7982 hdd_err("error starting the pre cac adapter");
7983 goto close_pre_cac_adapter;
7984 }
7985
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307986 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7987
7988 wiphy = hdd_ctx->wiphy;
7989 dev = pre_cac_adapter->dev;
7990
7991 /* Since this is only a dummy interface lets us use the IEs from the
7992 * other active SAP interface. In regular scenarios, these IEs would
7993 * come from the user space entity
7994 */
7995 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7996 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7997 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7998 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307999 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308000 }
8001 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
8002 ap_adapter->sessionCtx.ap.beacon,
8003 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
8004 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
8005 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
8006 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
8007 ap_adapter->sessionCtx.ap.sapConfig.authType;
8008
8009 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
8010 * to operate on the same bandwidth as that of the 2.4GHz operations.
8011 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
8012 */
8013 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
8014 case CH_WIDTH_20MHZ:
8015 channel_type = NL80211_CHAN_HT20;
8016 break;
8017 case CH_WIDTH_40MHZ:
8018 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
8019 ap_adapter->sessionCtx.ap.sapConfig.channel)
8020 channel_type = NL80211_CHAN_HT40PLUS;
8021 else
8022 channel_type = NL80211_CHAN_HT40MINUS;
8023 break;
8024 default:
8025 channel_type = NL80211_CHAN_NO_HT;
8026 break;
8027 }
8028
8029 freq = cds_chan_to_freq(pre_cac_chan);
8030 chan = __ieee80211_get_channel(wiphy, freq);
8031 if (!chan) {
8032 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308033 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308034 }
8035
8036 cfg80211_chandef_create(&chandef, chan, channel_type);
8037
8038 hdd_debug("orig width:%d channel_type:%d freq:%d",
8039 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
8040 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08008041 /*
8042 * Doing update after opening and starting pre-cac adapter will make
8043 * sure that driver won't do hardware mode change if there are any
8044 * initial hick-ups or issues in pre-cac adapter's configuration.
8045 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
8046 * connection update should result in DBS mode
8047 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008048 status = policy_mgr_update_and_wait_for_connection_update(
8049 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08008050 ap_adapter->sessionId,
8051 pre_cac_chan,
8052 SIR_UPDATE_REASON_PRE_CAC);
8053 if (QDF_IS_STATUS_ERROR(status)) {
8054 hdd_err("error in moving to DBS mode");
8055 goto stop_close_pre_cac_adapter;
8056 }
8057
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308058
8059 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
8060 if (0 != ret) {
8061 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308062 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308063 }
8064
8065 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
8066 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08008067 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308068 if (QDF_IS_STATUS_ERROR(status)) {
8069 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308070 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308071 }
8072
8073 /*
8074 * The pre cac status is set here. But, it would not be reset explicitly
8075 * anywhere, since after the pre cac success/failure, the pre cac
8076 * adapter itself would be removed.
8077 */
8078 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
8079 if (0 != ret) {
8080 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308081 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308082 }
8083
8084 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
8085 hdd_ap_ctx->operatingChannel);
8086 if (0 != ret) {
8087 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308088 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308089 }
8090
8091 ap_adapter->pre_cac_chan = pre_cac_chan;
8092
8093 return 0;
8094
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308095stop_close_pre_cac_adapter:
8096 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308097 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
8098 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308099close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308100 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08008101release_intf_addr_and_return_failure:
8102 /*
8103 * Release the interface address as the adapter
8104 * failed to start, if you don't release then next
8105 * adapter which is trying to come wouldn't get valid
8106 * mac address. Remember we have limited pool of mac addresses
8107 */
8108 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308109 return -EINVAL;
8110}
8111
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308112static const struct nla_policy
8113wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
8114 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
8115};
8116
Agrawal Ashish65634612016-08-18 13:24:32 +05308117static const struct nla_policy
8118wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
8119 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
8120 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
8121};
8122
8123/**
8124 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
8125 * @wiphy: Pointer to wireless phy
8126 * @wdev: Pointer to wireless device
8127 * @data: Pointer to data
8128 * @data_len: Length of @data
8129 *
8130 * This function parses the incoming NL vendor command data attributes and
8131 * updates the SAP context about channel_hint and DFS mode.
8132 * If channel_hint is set, SAP will choose that channel
8133 * as operating channel.
8134 *
8135 * If DFS mode is enabled, driver will include DFS channels
8136 * in ACS else driver will skip DFS channels.
8137 *
8138 * Return: 0 on success, negative errno on failure
8139 */
8140static int
8141__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8142 struct wireless_dev *wdev,
8143 const void *data, int data_len)
8144{
8145 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8146 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
8147 int ret;
8148 struct acs_dfs_policy *acs_policy;
8149 int mode = DFS_MODE_NONE;
8150 int channel_hint = 0;
8151
8152 ENTER_DEV(wdev->netdev);
8153
8154 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8155 hdd_err("Command not allowed in FTM mode");
8156 return -EINVAL;
8157 }
8158
8159 ret = wlan_hdd_validate_context(hdd_ctx);
8160 if (0 != ret)
8161 return ret;
8162
8163 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
8164 data, data_len,
8165 wlan_hdd_set_acs_dfs_config_policy)) {
8166 hdd_err("invalid attr");
8167 return -EINVAL;
8168 }
8169
8170 acs_policy = &hdd_ctx->acs_policy;
8171 /*
8172 * SCM sends this attribute to restrict SAP from choosing
8173 * DFS channels from ACS.
8174 */
8175 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
8176 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
8177
8178 if (!IS_DFS_MODE_VALID(mode)) {
8179 hdd_err("attr acs dfs mode is not valid");
8180 return -EINVAL;
8181 }
8182 acs_policy->acs_dfs_mode = mode;
8183
8184 /*
8185 * SCM sends this attribute to provide an active channel,
8186 * to skip redundant ACS between drivers, and save driver start up time
8187 */
8188 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
8189 channel_hint = nla_get_u8(
8190 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
8191
8192 if (!IS_CHANNEL_VALID(channel_hint)) {
8193 hdd_err("acs channel is not valid");
8194 return -EINVAL;
8195 }
8196 acs_policy->acs_channel = channel_hint;
8197
8198 return 0;
8199}
8200
8201/**
8202 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
8203 * @wiphy: wiphy structure pointer
8204 * @wdev: Wireless device structure pointer
8205 * @data: Pointer to the data received
8206 * @data_len: Length of @data
8207 *
8208 * This function parses the incoming NL vendor command data attributes and
8209 * updates the SAP context about channel_hint and DFS mode.
8210 *
8211 * Return: 0 on success; errno on failure
8212 */
8213static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8214 struct wireless_dev *wdev,
8215 const void *data, int data_len)
8216{
8217 int ret;
8218
8219 cds_ssr_protect(__func__);
8220 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
8221 cds_ssr_unprotect(__func__);
8222
8223 return ret;
8224}
8225
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308226/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308227 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
8228 * @mode : cfg80211 dfs mode
8229 *
8230 * Return: return csr sta roam dfs mode else return NONE
8231 */
8232static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
8233 enum dfs_mode mode)
8234{
8235 switch (mode) {
8236 case DFS_MODE_ENABLE:
8237 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
8238 break;
8239 case DFS_MODE_DISABLE:
8240 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
8241 break;
8242 case DFS_MODE_DEPRIORITIZE:
8243 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
8244 break;
8245 default:
8246 hdd_err("STA Roam policy dfs mode is NONE");
8247 return CSR_STA_ROAM_POLICY_NONE;
8248 }
8249}
8250
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308251/*
8252 * hdd_get_sap_operating_band: Get current operating channel
8253 * for sap.
8254 * @hdd_ctx: hdd context
8255 *
8256 * Return : Corresponding band for SAP operating channel
8257 */
8258uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
8259{
8260 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8261 QDF_STATUS status;
8262 hdd_adapter_t *adapter;
8263 uint8_t operating_channel = 0;
8264 uint8_t sap_operating_band = 0;
8265 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8266 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8267 adapter = adapter_node->pAdapter;
8268
8269 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
8270 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8271 &next);
8272 adapter_node = next;
8273 continue;
8274 }
8275 operating_channel = adapter->sessionCtx.ap.operatingChannel;
8276 if (IS_24G_CH(operating_channel))
8277 sap_operating_band = eCSR_BAND_24;
8278 else if (IS_5G_CH(operating_channel))
8279 sap_operating_band = eCSR_BAND_5G;
8280 else
8281 sap_operating_band = eCSR_BAND_ALL;
8282 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8283 &next);
bings373b99b2017-01-23 10:35:08 +08008284 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308285 }
8286 return sap_operating_band;
8287}
8288
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308289static const struct nla_policy
8290wlan_hdd_set_sta_roam_config_policy[
8291QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
8292 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
8293 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
8294};
8295
8296/**
8297 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
8298 * for station connection or roaming.
8299 * @wiphy: Pointer to wireless phy
8300 * @wdev: Pointer to wireless device
8301 * @data: Pointer to data
8302 * @data_len: Length of @data
8303 *
8304 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8305 * channels needs to be skipped in scanning or not.
8306 * If dfs_mode is disabled, driver will not scan DFS channels.
8307 * If skip_unsafe_channels is set, driver will skip unsafe channels
8308 * in Scanning.
8309 *
8310 * Return: 0 on success, negative errno on failure
8311 */
8312static int
8313__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8314 struct wireless_dev *wdev,
8315 const void *data, int data_len)
8316{
8317 struct net_device *dev = wdev->netdev;
8318 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8319 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8320 struct nlattr *tb[
8321 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8322 int ret;
8323 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8324 enum dfs_mode mode = DFS_MODE_NONE;
8325 bool skip_unsafe_channels = false;
8326 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308327 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308328
8329 ENTER_DEV(dev);
8330
8331 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8332 hdd_err("Command not allowed in FTM mode");
8333 return -EINVAL;
8334 }
8335
8336 ret = wlan_hdd_validate_context(hdd_ctx);
8337 if (0 != ret)
8338 return ret;
8339 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8340 data, data_len,
8341 wlan_hdd_set_sta_roam_config_policy)) {
8342 hdd_err("invalid attr");
8343 return -EINVAL;
8344 }
8345 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8346 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8347 if (!IS_DFS_MODE_VALID(mode)) {
8348 hdd_err("attr sta roam dfs mode policy is not valid");
8349 return -EINVAL;
8350 }
8351
8352 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8353
8354 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8355 skip_unsafe_channels = nla_get_u8(
8356 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308357 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308358 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308359 skip_unsafe_channels, adapter->sessionId,
8360 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308361
8362 if (!QDF_IS_STATUS_SUCCESS(status)) {
8363 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8364 return -EINVAL;
8365 }
8366 return 0;
8367}
8368
8369/**
8370 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8371 * connection and roaming for station.
8372 * @wiphy: wiphy structure pointer
8373 * @wdev: Wireless device structure pointer
8374 * @data: Pointer to the data received
8375 * @data_len: Length of @data
8376 *
8377 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8378 * channels needs to be skipped in scanning or not.
8379 * If dfs_mode is disabled, driver will not scan DFS channels.
8380 * If skip_unsafe_channels is set, driver will skip unsafe channels
8381 * in Scanning.
8382 * Return: 0 on success; errno on failure
8383 */
8384static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8385 struct wireless_dev *wdev,
8386 const void *data, int data_len)
8387{
8388 int ret;
8389
8390 cds_ssr_protect(__func__);
8391 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
8392 cds_ssr_unprotect(__func__);
8393
8394 return ret;
8395}
8396
Agrawal Ashish467dde42016-09-08 18:44:22 +05308397#ifdef FEATURE_WLAN_CH_AVOID
8398/**
8399 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8400 * is on unsafe channel.
8401 * @wiphy: wiphy structure pointer
8402 * @wdev: Wireless device structure pointer
8403 * @data: Pointer to the data received
8404 * @data_len: Length of @data
8405 *
8406 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8407 * on any of unsafe channels.
8408 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8409 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8410 *
8411 * Return: 0 on success; errno on failure
8412 */
8413static int
8414__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8415 struct wireless_dev *wdev,
8416 const void *data, int data_len)
8417{
8418 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8419 int ret;
8420 uint16_t unsafe_channel_count;
8421 int unsafe_channel_index;
8422 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8423
8424 ENTER_DEV(wdev->netdev);
8425
8426 if (!qdf_ctx) {
8427 cds_err("qdf_ctx is NULL");
8428 return -EINVAL;
8429 }
8430
8431 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8432 hdd_err("Command not allowed in FTM mode");
8433 return -EINVAL;
8434 }
8435
8436 ret = wlan_hdd_validate_context(hdd_ctx);
8437 if (0 != ret)
8438 return ret;
8439 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8440 &(hdd_ctx->unsafe_channel_count),
8441 sizeof(hdd_ctx->unsafe_channel_list));
8442
8443 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8444 (uint16_t)NUM_CHANNELS);
8445 for (unsafe_channel_index = 0;
8446 unsafe_channel_index < unsafe_channel_count;
8447 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008448 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308449 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8450 }
8451 hdd_unsafe_channel_restart_sap(hdd_ctx);
8452 return 0;
8453}
8454
8455/**
8456 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8457 * is on unsafe channel.
8458 * @wiphy: wiphy structure pointer
8459 * @wdev: Wireless device structure pointer
8460 * @data: Pointer to the data received
8461 * @data_len: Length of @data
8462 *
8463 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8464 * on any of unsafe channels.
8465 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8466 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8467 *
8468 * Return: 0 on success; errno on failure
8469 */
8470static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8471 struct wireless_dev *wdev,
8472 const void *data, int data_len)
8473{
8474 int ret;
8475
8476 cds_ssr_protect(__func__);
8477 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8478 cds_ssr_unprotect(__func__);
8479
8480 return ret;
8481}
8482
8483#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308484/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308485 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8486 * SAP is on unsafe channel.
8487 * @wiphy: wiphy structure pointer
8488 * @wdev: Wireless device structure pointer
8489 * @data: Pointer to the data received
8490 * @data_len: Length of @data
8491 *
8492 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8493 * driver.
8494 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8495 * will initiate restart of sap.
8496 *
8497 * Return: 0 on success; errno on failure
8498 */
8499static int
8500__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8501 struct wireless_dev *wdev,
8502 const void *data, int data_len)
8503{
8504 struct net_device *ndev = wdev->netdev;
8505 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8506 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8507 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8508 uint8_t config_channel = 0;
8509 hdd_ap_ctx_t *ap_ctx;
8510 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308511 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308512
8513 ENTER();
8514
8515 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008516 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308517 return -EINVAL;
8518 }
8519
8520 ret = wlan_hdd_validate_context(hdd_ctx);
8521 if (0 != ret)
8522 return -EINVAL;
8523
8524 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8525 data, data_len,
8526 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008527 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308528 return -EINVAL;
8529 }
8530
8531 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8532 if (!test_bit(SOFTAP_BSS_STARTED,
8533 &hostapd_adapter->event_flags)) {
8534 hdd_err("SAP is not started yet. Restart sap will be invalid");
8535 return -EINVAL;
8536 }
8537
8538 config_channel =
8539 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8540
8541 if (!((IS_24G_CH(config_channel)) ||
8542 (IS_5G_CH(config_channel)))) {
8543 hdd_err("Channel %d is not valid to restart SAP",
8544 config_channel);
8545 return -ENOTSUPP;
8546 }
8547
8548 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8549 ap_ctx->sapConfig.channel = config_channel;
8550 ap_ctx->sapConfig.ch_params.ch_width =
8551 ap_ctx->sapConfig.ch_width_orig;
8552
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008553 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8554 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308555 ap_ctx->sapConfig.sec_ch,
8556 &ap_ctx->sapConfig.ch_params);
8557
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008558 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308559 }
8560
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308561 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8562 uint32_t freq_len, i;
8563 uint32_t *freq;
8564 uint8_t chans[QDF_MAX_NUM_CHAN];
8565
8566 hdd_debug("setting mandatory freq/chan list");
8567
8568 freq_len = nla_len(
8569 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8570 sizeof(uint32_t);
8571
8572 if (freq_len > QDF_MAX_NUM_CHAN) {
8573 hdd_err("insufficient space to hold channels");
8574 return -ENOMEM;
8575 }
8576
8577 freq = nla_data(
8578 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8579
8580 hdd_debug("freq_len=%d", freq_len);
8581
8582 for (i = 0; i < freq_len; i++) {
8583 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8584 hdd_debug("freq[%d]=%d", i, freq[i]);
8585 }
8586
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008587 status = policy_mgr_set_sap_mandatory_channels(
8588 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308589 if (QDF_IS_STATUS_ERROR(status))
8590 return -EINVAL;
8591 }
8592
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308593 return 0;
8594}
8595
8596/**
8597 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8598 * @wiphy: wiphy structure pointer
8599 * @wdev: Wireless device structure pointer
8600 * @data: Pointer to the data received
8601 * @data_len: Length of @data
8602 *
8603 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8604 * driver.
8605 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8606 * will initiate restart of sap.
8607 *
8608 * Return: 0 on success; errno on failure
8609 */
8610static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8611 struct wireless_dev *wdev,
8612 const void *data, int data_len)
8613{
8614 int ret;
8615
8616 cds_ssr_protect(__func__);
8617 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8618 wdev, data, data_len);
8619 cds_ssr_unprotect(__func__);
8620
8621 return ret;
8622}
8623
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308624#undef BPF_INVALID
8625#undef BPF_SET_RESET
8626#undef BPF_VERSION
8627#undef BPF_ID
8628#undef BPF_PACKET_SIZE
8629#undef BPF_CURRENT_OFFSET
8630#undef BPF_PROGRAM
8631#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308632
8633/**
8634 * define short names for the global vendor params
8635 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8636 */
8637#define PARAM_TOTAL_CMD_EVENT_WAKE \
8638 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8639#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8640 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8641#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8642 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8643#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8644 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8645#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8646 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8647#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8648 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8649#define PARAM_TOTAL_RX_DATA_WAKE \
8650 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8651#define PARAM_RX_UNICAST_CNT \
8652 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8653#define PARAM_RX_MULTICAST_CNT \
8654 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8655#define PARAM_RX_BROADCAST_CNT \
8656 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8657#define PARAM_ICMP_PKT \
8658 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8659#define PARAM_ICMP6_PKT \
8660 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8661#define PARAM_ICMP6_RA \
8662 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8663#define PARAM_ICMP6_NA \
8664 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8665#define PARAM_ICMP6_NS \
8666 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8667#define PARAM_ICMP4_RX_MULTICAST_CNT \
8668 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8669#define PARAM_ICMP6_RX_MULTICAST_CNT \
8670 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8671#define PARAM_OTHER_RX_MULTICAST_CNT \
8672 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308673#define PARAM_RSSI_BREACH_CNT \
8674 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8675#define PARAM_LOW_RSSI_CNT \
8676 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8677#define PARAM_GSCAN_CNT \
8678 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8679#define PARAM_PNO_COMPLETE_CNT \
8680 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8681#define PARAM_PNO_MATCH_CNT \
8682 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8683
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308684
8685
8686/**
8687 * hdd_send_wakelock_stats() - API to send wakelock stats
8688 * @ctx: context to be passed to callback
8689 * @data: data passed to callback
8690 *
8691 * This function is used to send wake lock stats to HAL layer
8692 *
8693 * Return: 0 on success, error number otherwise.
8694 */
8695static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8696 const struct sir_wake_lock_stats *data)
8697{
8698 struct sk_buff *skb;
8699 uint32_t nl_buf_len;
8700 uint32_t total_rx_data_wake, rx_multicast_cnt;
8701 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308702 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308703
8704 ENTER();
8705
8706 nl_buf_len = NLMSG_HDRLEN;
8707 nl_buf_len +=
8708 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8709 (NLMSG_HDRLEN + sizeof(uint32_t));
8710
8711 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8712
8713 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008714 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308715 return -ENOMEM;
8716 }
8717
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008718 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308719 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008720 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308721 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008722 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308723 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008724 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308725 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008726 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308727 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008728 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308729 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008730 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308731 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008732 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8733 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308734 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008735 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308736 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008737 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308738 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008739 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308740 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008741 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308742 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008743 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308744 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308745
8746 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308747 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308748
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308749 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308750 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308751
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308752 rx_multicast_cnt =
8753 data->wow_ipv4_mcast_wake_up_count +
8754 ipv6_rx_multicast_addr_cnt;
8755
8756 total_rx_data_wake =
8757 data->wow_ucast_wake_up_count +
8758 data->wow_bcast_wake_up_count +
8759 rx_multicast_cnt;
8760
8761 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8762 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8763 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8764 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8765 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8766 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8767 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8768 total_rx_data_wake) ||
8769 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8770 data->wow_ucast_wake_up_count) ||
8771 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8772 rx_multicast_cnt) ||
8773 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8774 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308775 nla_put_u32(skb, PARAM_ICMP_PKT,
8776 data->wow_icmpv4_count) ||
8777 nla_put_u32(skb, PARAM_ICMP6_PKT,
8778 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308779 nla_put_u32(skb, PARAM_ICMP6_RA,
8780 data->wow_ipv6_mcast_ra_stats) ||
8781 nla_put_u32(skb, PARAM_ICMP6_NA,
8782 data->wow_ipv6_mcast_na_stats) ||
8783 nla_put_u32(skb, PARAM_ICMP6_NS,
8784 data->wow_ipv6_mcast_ns_stats) ||
8785 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8786 data->wow_ipv4_mcast_wake_up_count) ||
8787 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8788 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308789 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8790 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8791 data->wow_rssi_breach_wake_up_count) ||
8792 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8793 data->wow_low_rssi_wake_up_count) ||
8794 nla_put_u32(skb, PARAM_GSCAN_CNT,
8795 data->wow_gscan_wake_up_count) ||
8796 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8797 data->wow_pno_complete_wake_up_count) ||
8798 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8799 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008800 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308801 goto nla_put_failure;
8802 }
8803
8804 cfg80211_vendor_cmd_reply(skb);
8805
8806 EXIT();
8807 return 0;
8808
8809nla_put_failure:
8810 kfree_skb(skb);
8811 return -EINVAL;
8812}
8813
8814/**
8815 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8816 * @wiphy: wiphy pointer
8817 * @wdev: pointer to struct wireless_dev
8818 * @data: pointer to incoming NL vendor data
8819 * @data_len: length of @data
8820 *
8821 * This function parses the incoming NL vendor command data attributes and
8822 * invokes the SME Api and blocks on a completion variable.
8823 * WMA copies required data and invokes callback
8824 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8825 *
8826 * Return: 0 on success; error number otherwise.
8827 */
8828static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8829 struct wireless_dev *wdev,
8830 const void *data,
8831 int data_len)
8832{
8833 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8834 int status, ret;
8835 struct sir_wake_lock_stats wake_lock_stats;
8836 QDF_STATUS qdf_status;
8837
8838 ENTER();
8839
8840 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008841 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308842 return -EINVAL;
8843 }
8844
8845 status = wlan_hdd_validate_context(hdd_ctx);
8846 if (0 != status)
8847 return -EINVAL;
8848
8849 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8850 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008851 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308852 return -EINVAL;
8853 }
8854
8855 ret = hdd_send_wakelock_stats(hdd_ctx,
8856 &wake_lock_stats);
8857 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008858 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308859
8860 EXIT();
8861 return ret;
8862}
8863
8864/**
8865 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8866 * @wiphy: wiphy pointer
8867 * @wdev: pointer to struct wireless_dev
8868 * @data: pointer to incoming NL vendor data
8869 * @data_len: length of @data
8870 *
8871 * This function parses the incoming NL vendor command data attributes and
8872 * invokes the SME Api and blocks on a completion variable.
8873 * WMA copies required data and invokes callback
8874 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8875 *
8876 * Return: 0 on success; error number otherwise.
8877 */
8878static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8879 struct wireless_dev *wdev,
8880 const void *data, int data_len)
8881{
8882 int ret;
8883
8884 cds_ssr_protect(__func__);
8885 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8886 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008887 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308888
8889 return ret;
8890}
8891
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308892/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308893 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8894 * @wiphy: wiphy structure pointer
8895 * @wdev: Wireless device structure pointer
8896 * @data: Pointer to the data received
8897 * @data_len: Length of @data
8898 *
8899 * This function reads wmi max bus size and fill in the skb with
8900 * NL attributes and send up the NL event.
8901 * Return: 0 on success; errno on failure
8902 */
8903static int
8904__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8905 struct wireless_dev *wdev,
8906 const void *data, int data_len)
8907{
8908 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8909 int ret_val;
8910 struct sk_buff *skb;
8911 uint32_t nl_buf_len;
8912
8913 ENTER();
8914
8915 ret_val = wlan_hdd_validate_context(hdd_ctx);
8916 if (ret_val)
8917 return ret_val;
8918
8919 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8920 hdd_err("Command not allowed in FTM mode");
8921 return -EINVAL;
8922 }
8923
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008924 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308925
8926 nl_buf_len = NLMSG_HDRLEN;
8927 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8928
8929 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8930 if (!skb) {
8931 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8932 return -ENOMEM;
8933 }
8934
8935 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8936 hdd_ctx->wmi_max_len)) {
8937 hdd_err("nla put failure");
8938 goto nla_put_failure;
8939 }
8940
8941 cfg80211_vendor_cmd_reply(skb);
8942
8943 EXIT();
8944
8945 return 0;
8946
8947nla_put_failure:
8948 kfree_skb(skb);
8949 return -EINVAL;
8950}
8951
8952/**
8953 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8954 * @wiphy: wiphy structure pointer
8955 * @wdev: Wireless device structure pointer
8956 * @data: Pointer to the data received
8957 * @data_len: Length of @data
8958 *
8959 * Return: 0 on success; errno on failure
8960 */
8961static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8962 struct wireless_dev *wdev,
8963 const void *data, int data_len)
8964{
8965 int ret;
8966
8967 cds_ssr_protect(__func__);
8968 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8969 cds_ssr_unprotect(__func__);
8970
8971 return ret;
8972}
8973
8974/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308975 *__wlan_hdd_cfg80211_setband() - set band
8976 * @wiphy: Pointer to wireless phy
8977 * @wdev: Pointer to wireless device
8978 * @data: Pointer to data
8979 * @data_len: Length of @data
8980 *
8981 * Return: 0 on success, negative errno on failure
8982 */
8983static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8984 struct wireless_dev *wdev,
8985 const void *data, int data_len)
8986{
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308987 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008988 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308989 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8990 int ret;
8991 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8992 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8993
8994 ENTER();
8995
8996 ret = wlan_hdd_validate_context(hdd_ctx);
8997 if (ret)
8998 return ret;
8999
9000 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
9001 hdd_err(FL("Invalid ATTR"));
9002 return -EINVAL;
9003 }
9004
9005 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
9006 hdd_err(FL("attr SETBAND_VALUE failed"));
9007 return -EINVAL;
9008 }
9009
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07009010 ret = hdd_reg_set_band(dev,
9011 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309012
9013 EXIT();
9014 return ret;
9015}
9016
9017/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309018 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
9019 * @adapter: hdd adapter
9020 * @channel: channel number
9021 *
9022 * return: QDF status based on success or failure
9023 */
9024static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
9025 int channel, int chan_bw)
9026{
9027 if (QDF_STATUS_SUCCESS !=
9028 wlan_hdd_validate_operation_channel(adapter, channel))
9029 return QDF_STATUS_E_FAILURE;
9030 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9031 channel,
9032 PHY_SINGLE_CHANNEL_CENTERED))) {
9033 hdd_notice("channel %d is in nol", channel);
9034 return -EINVAL;
9035 }
9036
9037 if ((wlansap_is_channel_leaking_in_nol(
9038 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9039 channel, chan_bw))) {
9040 hdd_notice("channel %d is leaking in nol", channel);
9041 return -EINVAL;
9042 }
9043
9044 return 0;
9045
9046}
9047
Kapil Gupta8878ad92017-02-13 11:56:04 +05309048static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
9049 tsap_Config_t *sap_config,
9050 struct hdd_vendor_chan_info *channel_list)
9051{
9052 sap_config->channel = channel_list->pri_ch;
9053
9054 sap_config->ch_params.center_freq_seg0 =
9055 channel_list->vht_seg0_center_ch;
9056 sap_config->ch_params.center_freq_seg1 =
9057 channel_list->vht_seg1_center_ch;
9058
9059 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
9060 sap_config->ch_params.ch_width = channel_list->chan_width;
9061 if (sap_config->channel >= 36)
9062 sap_config->ch_width_orig =
9063 hdd_ctx->config->vhtChannelWidth;
9064 else
9065 sap_config->ch_width_orig =
9066 hdd_ctx->config->nChannelBondingMode24GHz ?
9067 eHT_CHANNEL_WIDTH_40MHZ :
9068 eHT_CHANNEL_WIDTH_20MHZ;
9069
9070 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
9071 sap_config->acs_cfg.ch_width = channel_list->chan_width;
9072 sap_config->acs_cfg.vht_seg0_center_ch =
9073 channel_list->vht_seg0_center_ch;
9074 sap_config->acs_cfg.vht_seg1_center_ch =
9075 channel_list->vht_seg1_center_ch;
9076 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
9077}
9078
9079static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
9080 uint8_t channel_cnt,
9081 struct hdd_vendor_chan_info *channel_list)
9082{
9083 tsap_Config_t *sap_config;
9084 hdd_ap_ctx_t *hdd_ap_ctx;
9085 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9086 QDF_STATUS status = QDF_STATUS_SUCCESS;
9087
9088 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
9089 sap_config = &adapter->sessionCtx.ap.sapConfig;
9090
9091 if (QDF_TIMER_STATE_RUNNING ==
9092 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
9093 ap.vendor_acs_timer)) {
9094 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
9095 }
9096
9097 if (channel_list && channel_list->pri_ch == 0) {
9098 /* Check mode, set default channel */
9099 channel_list->pri_ch = 6;
9100 /*
9101 * sap_select_default_oper_chan(hdd_ctx->hHal,
9102 * sap_config->acs_cfg.hw_mode);
9103 */
9104 }
9105
9106 switch (reason) {
9107 /* SAP init case */
9108 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
9109 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
9110 /* Update Hostapd */
9111 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
9112 break;
9113
9114 /* DFS detected on current channel */
9115 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
9116 wlan_sap_update_next_channel(
9117 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9118 channel_list->pri_ch,
9119 channel_list->chan_width);
9120 status = sme_update_new_channel_event(
9121 WLAN_HDD_GET_HAL_CTX(adapter),
9122 adapter->sessionId);
9123 break;
9124
9125 /* LTE coex event on current channel */
9126 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
9127 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
9128 sap_config->acs_cfg.ch_width = channel_list->chan_width;
9129 hdd_ap_ctx->sapConfig.ch_width_orig =
9130 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08009131 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309132 break;
9133
9134 default:
9135 hdd_info("invalid reason for timer invoke");
9136 }
9137 qdf_mem_free(channel_list);
9138 EXIT();
9139 return status;
9140}
9141
9142/**
9143 * Define short name for vendor channel set config
9144 */
9145#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
9146#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
9147#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
9148#define SET_CHAN_PRIMARY_CHANNEL \
9149 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
9150#define SET_CHAN_SECONDARY_CHANNEL \
9151 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
9152#define SET_CHAN_SEG0_CENTER_CHANNEL \
9153 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
9154#define SET_CHAN_SEG1_CENTER_CHANNEL \
9155 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
9156#define SET_CHAN_CHANNEL_WIDTH \
9157 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
9158#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
9159
9160/**
9161 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
9162 * @channel_list: pointer to hdd_vendor_chan_info
9163 * @reason: channel change reason
9164 * @channel_cnt: channel count
9165 * @data: data
9166 * @data_len: data len
9167 *
9168 * Return: 0 on success, negative errno on failure
9169 */
9170static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
9171 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
9172 const void *data, int data_len)
9173{
9174 int rem, i = 0;
9175 struct nlattr *tb[SET_CHAN_MAX + 1];
9176 struct nlattr *tb2[SET_CHAN_MAX + 1];
9177 struct nlattr *curr_attr;
9178 struct hdd_vendor_chan_info *channel_list;
9179
9180 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
9181 hdd_err("Invalid ATTR");
9182 return -EINVAL;
9183 }
9184
9185 if (tb[SET_CHAN_REASON])
9186 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
9187
9188 if (tb[SET_CHAN_CHANNEL_COUNT]) {
9189 *channel_cnt = nla_get_u8(tb[
9190 SET_CHAN_CHANNEL_COUNT]);
9191 hdd_info("channel count %d", *channel_cnt);
9192 }
9193
9194 if (!(*channel_cnt)) {
9195 hdd_err("channel count is %d", *channel_cnt);
9196 return -EINVAL;
9197 }
9198
9199 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
9200 (*channel_cnt));
9201
9202 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
9203 if (nla_parse(tb2,
9204 SET_CHAN_MAX,
9205 nla_data(curr_attr), nla_len(curr_attr),
9206 NULL)) {
9207 hdd_err("nla_parse failed");
9208 return -EINVAL;
9209 }
9210 /* Parse and Fetch allowed SSID list*/
9211 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
9212 channel_list[i].pri_ch =
9213 nla_get_u8(
9214 tb2[SET_CHAN_PRIMARY_CHANNEL]);
9215 }
9216 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
9217 channel_list[i].ht_sec_ch =
9218 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
9219 }
9220 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
9221 channel_list[i].vht_seg0_center_ch =
9222 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
9223 }
9224 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
9225 channel_list[i].vht_seg1_center_ch =
9226 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
9227 }
9228 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
9229 channel_list[i].chan_width =
9230 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
9231 }
9232 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
9233 i, channel_list[i].pri_ch,
9234 channel_list[i].ht_sec_ch,
9235 channel_list[i].vht_seg0_center_ch,
9236 channel_list[i].vht_seg1_center_ch,
9237 channel_list[i].chan_width);
9238 i++;
9239 if (i > *channel_cnt)
9240 break;
9241 }
9242 *chan_list_ptr = channel_list;
9243
9244 return 0;
9245}
9246
9247/**
9248 * Undef short names for vendor set channel configuration
9249 */
9250#undef SET_CHAN_REASON
9251#undef SET_CHAN_CHANNEL_COUNT
9252#undef SET_CHAN_CHAN_LIST
9253#undef SET_CHAN_PRIMARY_CHANNEL
9254#undef SET_CHAN_SECONDARY_CHANNEL
9255#undef SET_CHAN_SEG0_CENTER_CHANNEL
9256#undef SET_CHAN_SEG1_CENTER_CHANNEL
9257#undef SET_CHAN_CHANNEL_WIDTH
9258#undef SET_CHAN_MAX
9259
9260/**
9261 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9262 * @wiphy: Pointer to wireless phy
9263 * @wdev: Pointer to wireless device
9264 * @data: Pointer to data
9265 * @data_len: Length of @data
9266 *
9267 * Return: 0 on success, negative errno on failure
9268 */
9269static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9270 struct wireless_dev *wdev,
9271 const void *data, int data_len)
9272{
9273 int ret_val;
9274 QDF_STATUS qdf_status;
9275 uint8_t channel_cnt = 0, reason = -1;
9276 struct hdd_vendor_chan_info *channel_list = NULL;
9277 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
9278 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9279
9280 ENTER();
9281
9282 ret_val = wlan_hdd_validate_context(hdd_ctx);
9283 if (ret_val)
9284 return ret_val;
9285
9286 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9287 hdd_err("Command not allowed in FTM mode");
9288 return -EINVAL;
9289 }
9290
9291 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
9292 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
9293 else {
9294 hdd_err("already timeout happened for acs");
9295 return -EINVAL;
9296 }
9297
9298 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
9299 &channel_cnt, data, data_len);
9300 if (ret_val)
9301 return ret_val;
9302
9303 /* Validate channel to be set */
9304 while (channel_cnt && channel_list) {
9305 qdf_status = wlan_hdd_validate_acs_channel(adapter,
9306 channel_list->pri_ch,
9307 channel_list->chan_width);
9308 if (qdf_status == QDF_STATUS_SUCCESS)
9309 break;
9310 channel_cnt--;
9311 channel_list++;
9312 }
9313 if ((channel_cnt <= 0) || !channel_list) {
9314 hdd_err("no available channel/chanlist %p", channel_list);
9315 return -EINVAL;
9316 }
9317
9318 qdf_status = hdd_update_acs_channel(adapter, reason,
9319 channel_cnt, channel_list);
9320 return qdf_status_to_os_return(qdf_status);
9321}
9322
9323/**
9324 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9325 * @wiphy: Pointer to wireless phy
9326 * @wdev: Pointer to wireless device
9327 * @data: Pointer to data
9328 * @data_len: Length of @data
9329 *
9330 * Return: 0 on success, negative errno on failure
9331 */
9332static int wlan_hdd_cfg80211_update_vendor_channel(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_update_vendor_channel(wiphy, wdev, data,
9340 data_len);
9341 cds_ssr_protect(__func__);
9342
9343 return ret;
9344}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309345
9346/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309347 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9348 * @wiphy: wiphy structure pointer
9349 * @wdev: Wireless device structure pointer
9350 * @data: Pointer to the data received
9351 * @data_len: Length of @data
9352 *
9353 * Return: 0 on success; errno on failure
9354 */
9355static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9356 struct wireless_dev *wdev,
9357 const void *data, int data_len)
9358{
9359 int ret;
9360
9361 cds_ssr_protect(__func__);
9362 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9363 cds_ssr_unprotect(__func__);
9364
9365 return ret;
9366}
9367
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009368/**
9369 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9370 * @nl80211_value: Vendor command attribute value
9371 * @wmi_value: Pointer to return converted WMI return value
9372 *
9373 * Convert NL80211 vendor command value for SAR limit set to WMI value
9374 * Return: 0 on success, -1 on invalid value
9375 */
9376static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9377 u32 *wmi_value)
9378{
9379 int ret = 0;
9380
9381 switch (nl80211_value) {
9382 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9383 *wmi_value = WMI_SAR_FEATURE_OFF;
9384 break;
9385 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9386 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9387 break;
9388 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9389 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9390 break;
9391 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9392 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9393 break;
9394 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9395 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9396 break;
9397 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9398 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9399 break;
9400 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9401 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9402 break;
9403 default:
9404 ret = -1;
9405 }
9406 return ret;
9407}
9408
9409/**
9410 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9411 * @nl80211_value: Vendor command attribute value
9412 * @wmi_value: Pointer to return converted WMI return value
9413 *
9414 * Convert NL80211 vendor command value for SAR BAND to WMI value
9415 * Return: 0 on success, -1 on invalid value
9416 */
9417static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9418{
9419 int ret = 0;
9420
9421 switch (nl80211_value) {
9422 case NL80211_BAND_2GHZ:
9423 *wmi_value = WMI_SAR_2G_ID;
9424 break;
9425 case NL80211_BAND_5GHZ:
9426 *wmi_value = WMI_SAR_5G_ID;
9427 break;
9428 default:
9429 ret = -1;
9430 }
9431 return ret;
9432}
9433
9434/**
9435 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9436 * @nl80211_value: Vendor command attribute value
9437 * @wmi_value: Pointer to return converted WMI return value
9438 *
9439 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9440 * Return: 0 on success, -1 on invalid value
9441 */
9442static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9443 u32 *wmi_value)
9444{
9445 int ret = 0;
9446
9447 switch (nl80211_value) {
9448 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9449 *wmi_value = WMI_SAR_MOD_CCK;
9450 break;
9451 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9452 *wmi_value = WMI_SAR_MOD_OFDM;
9453 break;
9454 default:
9455 ret = -1;
9456 }
9457 return ret;
9458}
9459
9460
9461/**
9462 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9463 * @wiphy: Pointer to wireless phy
9464 * @wdev: Pointer to wireless device
9465 * @data: Pointer to data
9466 * @data_len: Length of @data
9467 *
9468 * This function is used to setup Specific Absorption Rate limit specs.
9469 *
9470 * Return: 0 on success, negative errno on failure
9471 */
9472static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9473 struct wireless_dev *wdev,
9474 const void *data, int data_len)
9475{
9476 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9477 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9478 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9479 *sar_spec_list;
9480 struct sar_limit_cmd_params sar_limit_cmd = {0};
9481 int ret = -EINVAL, i = 0, rem = 0;
9482
9483 ENTER();
9484
9485 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9486 hdd_err("Command not allowed in FTM mode");
9487 return -EPERM;
9488 }
9489
9490 if (wlan_hdd_validate_context(hdd_ctx))
9491 return -EINVAL;
9492
9493 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9494 data, data_len, NULL)) {
9495 hdd_err("Invalid SAR attributes");
9496 return -EINVAL;
9497 }
9498
9499 /* Vendor command manadates all SAR Specs in single call */
9500 sar_limit_cmd.commit_limits = 1;
9501 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9502 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9503 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9504 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9505 &sar_limit_cmd.sar_enable) < 0) {
9506 hdd_err("Invalid SAR Enable attr");
9507 goto fail;
9508 }
9509 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009510 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009511
9512 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9513 sar_limit_cmd.num_limit_rows = nla_get_u32(
9514 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009515 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009516 sar_limit_cmd.num_limit_rows);
9517 }
9518 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9519 hdd_err("SAR Spec list exceed supported size");
9520 goto fail;
9521 }
9522 if (sar_limit_cmd.num_limit_rows == 0)
9523 goto send_sar_limits;
9524 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9525 struct sar_limit_cmd_row) *
9526 sar_limit_cmd.num_limit_rows);
9527 if (!sar_limit_cmd.sar_limit_row_list) {
9528 ret = -ENOMEM;
9529 goto fail;
9530 }
9531 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9532 hdd_err("Invalid SAR SPECs list");
9533 goto fail;
9534 }
9535
9536 nla_for_each_nested(sar_spec_list,
9537 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9538 if (i == sar_limit_cmd.num_limit_rows) {
9539 hdd_warn("SAR Cmd has excess SPECs in list");
9540 break;
9541 }
9542
9543 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9544 nla_data(sar_spec_list), nla_len(sar_spec_list),
9545 NULL)) {
9546 hdd_err("nla_parse failed for SAR Spec list");
9547 goto fail;
9548 }
9549 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9550 if (sar_spec[
9551 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9552 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9553 nla_get_u32(sar_spec[
9554 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9555 } else {
9556 hdd_err("SAR Spec does not have power limit value");
9557 goto fail;
9558 }
9559
9560 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9561 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9562 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9563 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9564 < 0) {
9565 hdd_err("Invalid SAR Band attr");
9566 goto fail;
9567 }
9568 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9569 WMI_SAR_BAND_ID_VALID_MASK;
9570 }
9571 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9572 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9573 nla_get_u32(sar_spec[
9574 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9575 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9576 WMI_SAR_CHAIN_ID_VALID_MASK;
9577 }
9578 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9579 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9580 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9581 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9582 < 0) {
9583 hdd_err("Invalid SAR Modulation attr");
9584 goto fail;
9585 }
9586 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9587 WMI_SAR_MOD_ID_VALID_MASK;
9588 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009589 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009590 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9591 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9592 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9593 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9594 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9595 i++;
9596 }
9597
9598 if (i < sar_limit_cmd.num_limit_rows) {
9599 hdd_warn("SAR Cmd has less SPECs in list");
9600 sar_limit_cmd.num_limit_rows = i;
9601 }
9602
9603send_sar_limits:
9604 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9605 QDF_STATUS_SUCCESS)
9606 ret = 0;
9607fail:
9608 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9609 return ret;
9610}
9611
9612/**
9613 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9614 * @wiphy: Pointer to wireless phy
9615 * @wdev: Pointer to wireless device
9616 * @data: Pointer to data
9617 * @data_len: Length of @data
9618 *
9619 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9620 *
9621 * Return: 0 on success, negative errno on failure
9622 */
9623static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9624 struct wireless_dev *wdev,
9625 const void *data,
9626 int data_len)
9627{
9628 int ret;
9629
9630 cds_ssr_protect(__func__);
9631 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9632 data_len);
9633 cds_ssr_unprotect(__func__);
9634
9635 return ret;
9636}
9637
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309638static const struct
9639nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9640 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9641 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9642 .len = QDF_MAC_ADDR_SIZE},
9643};
9644
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309645void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9646{
9647 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9648 hdd_adapter_t *adapter;
9649
9650 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9651 if (!adapter) {
9652 hdd_err("adapter NULL");
9653 return;
9654 }
9655
9656 adapter->lfr_fw_status.is_disabled = rso_status->status;
9657 complete(&adapter->lfr_fw_status.disable_lfr_event);
9658}
9659
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309660/**
9661 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9662 * @wiphy: Pointer to wireless phy
9663 * @wdev: Pointer to wireless device
9664 * @data: Pointer to data
9665 * @data_len: Length of @data
9666 *
9667 * This function is used to enable/disable roaming using vendor commands
9668 *
9669 * Return: 0 on success, negative errno on failure
9670 */
9671static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9672 struct wireless_dev *wdev,
9673 const void *data, int data_len)
9674{
9675 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9676 struct net_device *dev = wdev->netdev;
9677 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9678 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309679 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309680 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309681 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309682 unsigned long rc;
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309683 hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309684
9685 ENTER_DEV(dev);
9686
9687 ret = wlan_hdd_validate_context(hdd_ctx);
9688 if (0 != ret)
9689 return ret;
9690
9691 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9692 hdd_err("Command not allowed in FTM mode");
9693 return -EINVAL;
9694 }
9695
9696 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9697 qca_wlan_vendor_attr);
9698 if (ret) {
9699 hdd_err("Invalid ATTR");
9700 return -EINVAL;
9701 }
9702
9703 /* Parse and fetch Enable flag */
9704 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9705 hdd_err("attr enable failed");
9706 return -EINVAL;
9707 }
9708
9709 is_fast_roam_enabled = nla_get_u32(
9710 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009711 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009712 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309713
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009714 if (!adapter->fast_roaming_allowed) {
9715 hdd_err("fast roaming not allowed on %s interface",
9716 adapter->dev->name);
9717 return -EINVAL;
9718 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309719 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309720 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309721 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309722 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309723 if (qdf_status != QDF_STATUS_SUCCESS)
9724 hdd_err("sme_config_fast_roaming failed with status=%d",
9725 qdf_status);
9726 ret = qdf_status_to_os_return(qdf_status);
9727
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309728 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
9729 QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9730
9731 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309732 /*
9733 * wait only for LFR disable in fw as LFR enable
9734 * is always success
9735 */
9736 rc = wait_for_completion_timeout(
9737 &adapter->lfr_fw_status.disable_lfr_event,
9738 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9739 if (!rc) {
9740 hdd_err("Timed out waiting for RSO CMD status");
9741 return -ETIMEDOUT;
9742 }
9743
9744 if (!adapter->lfr_fw_status.is_disabled) {
9745 hdd_err("Roam disable attempt in FW fails");
9746 return -EBUSY;
9747 }
9748 }
9749
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309750 EXIT();
9751 return ret;
9752}
9753
9754/**
9755 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9756 * @wiphy: Pointer to wireless phy
9757 * @wdev: Pointer to wireless device
9758 * @data: Pointer to data
9759 * @data_len: Length of @data
9760 *
9761 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9762 *
9763 * Return: 0 on success, negative errno on failure
9764 */
9765static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9766 struct wireless_dev *wdev,
9767 const void *data, int data_len)
9768{
9769 int ret;
9770
9771 cds_ssr_protect(__func__);
9772 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9773 cds_ssr_unprotect(__func__);
9774
9775 return ret;
9776}
9777
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309778
9779void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9780 uint32_t vdev_id)
9781{
9782 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9783 int status;
9784 hdd_adapter_t *adapter = NULL;
9785 hdd_station_ctx_t *hdd_sta_ctx;
9786
9787 status = wlan_hdd_validate_context(hdd_ctx);
9788 if (status != 0)
9789 return;
9790
9791 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9792 if (adapter == NULL) {
9793 hdd_err("vdev_id %d does not exist with host", vdev_id);
9794 return;
9795 }
9796
9797 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9798 hdd_sta_ctx->conn_info.cca = congestion;
9799 hdd_info("congestion:%d", congestion);
9800}
9801
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309802static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9803 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9804 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9805 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9806 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9807};
9808
9809/**
9810 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9811 * @wiphy: Pointer to wireless phy
9812 * @wdev: Pointer to wireless device
9813 * @data: Pointer to data
9814 * @data_len: Length of @data
9815 *
9816 * Return: 0 on success, negative errno on failure
9817 */
9818static int
9819__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9820 struct wireless_dev *wdev,
9821 const void *data,
9822 int data_len)
9823{
9824 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9825 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9826 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9827 struct nlattr *apth;
9828 int rem;
9829 int ret = 1;
9830 int print_idx = -1;
9831 int module_id = -1;
9832 int bit_mask = -1;
9833 int status;
9834
9835 ENTER();
9836
9837 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9838 hdd_err("Command not allowed in FTM mode");
9839 return -EINVAL;
9840 }
9841
9842 ret = wlan_hdd_validate_context(hdd_ctx);
9843 if (ret != 0)
9844 return -EINVAL;
9845
9846 print_idx = qdf_get_pidx();
9847 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9848 hdd_err("Invalid print controle object index");
9849 return -EINVAL;
9850 }
9851
9852 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9853 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9854 hdd_err("Invalid attr");
9855 return -EINVAL;
9856 }
9857
9858 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9859 hdd_err("attr trace level param failed");
9860 return -EINVAL;
9861 }
9862
9863 nla_for_each_nested(apth,
9864 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9865 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9866 nla_data(apth), nla_len(apth), NULL)) {
9867 hdd_err("Invalid attr");
9868 return -EINVAL;
9869 }
9870
9871 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9872 hdd_err("attr Module ID failed");
9873 return -EINVAL;
9874 }
9875 module_id = nla_get_u32
9876 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9877
9878 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9879 hdd_err("attr Verbose mask failed");
9880 return -EINVAL;
9881 }
9882 bit_mask = nla_get_u32
9883 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9884
9885 status = hdd_qdf_trace_enable(module_id, bit_mask);
9886
9887 if (status != 0)
9888 hdd_err("can not set verbose mask %d for the category %d",
9889 bit_mask, module_id);
9890 }
9891
9892 EXIT();
9893 return ret;
9894}
9895
9896/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309897 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9898 * @wiphy: Pointer to wireless phy
9899 * @wdev: Pointer to wireless device
9900 * @data: Pointer to data
9901 * @data_len: Length of @data
9902 *
9903 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9904 *
9905 * Return: 0 on success, negative errno on failure
9906 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309907
9908static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9909 struct wireless_dev *wdev,
9910 const void *data,
9911 int data_len)
9912{
9913 int ret;
9914
9915 cds_ssr_protect(__func__);
9916 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9917 cds_ssr_unprotect(__func__);
9918
9919 return ret;
9920}
9921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009922const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9923 {
9924 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9925 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9926 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309927 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009928 .doit = is_driver_dfs_capable
9929 },
9930
9931#ifdef WLAN_FEATURE_NAN
9932 {
9933 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9934 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9935 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9936 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9937 .doit = wlan_hdd_cfg80211_nan_request
9938 },
9939#endif
9940
9941#ifdef WLAN_FEATURE_STATS_EXT
9942 {
9943 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9944 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9945 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9946 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9947 .doit = wlan_hdd_cfg80211_stats_ext_request
9948 },
9949#endif
9950#ifdef FEATURE_WLAN_EXTSCAN
9951 {
9952 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9953 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9954 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9955 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9956 .doit = wlan_hdd_cfg80211_extscan_start
9957 },
9958 {
9959 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9960 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9961 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9962 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9963 .doit = wlan_hdd_cfg80211_extscan_stop
9964 },
9965 {
9966 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9967 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9968 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9969 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9970 },
9971 {
9972 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9973 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9974 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9975 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9976 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9977 },
9978 {
9979 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9980 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9981 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9982 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9983 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9984 },
9985 {
9986 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9987 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9988 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9989 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9990 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9991 },
9992 {
9993 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9994 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9995 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9996 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9997 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9998 },
9999 {
10000 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10001 .info.subcmd =
10002 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
10003 .flags =
10004 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
10005 WIPHY_VENDOR_CMD_NEED_RUNNING,
10006 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
10007 },
10008 {
10009 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10010 .info.subcmd =
10011 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
10012 .flags =
10013 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
10014 WIPHY_VENDOR_CMD_NEED_RUNNING,
10015 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
10016 },
10017 {
10018 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10019 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
10020 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10021 WIPHY_VENDOR_CMD_NEED_NETDEV |
10022 WIPHY_VENDOR_CMD_NEED_RUNNING,
10023 .doit = wlan_hdd_cfg80211_set_epno_list
10024 },
10025#endif /* FEATURE_WLAN_EXTSCAN */
10026
10027#ifdef WLAN_FEATURE_LINK_LAYER_STATS
10028 {
10029 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10030 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
10031 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10032 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10033 .doit = wlan_hdd_cfg80211_ll_stats_clear
10034 },
10035
10036 {
10037 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10038 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
10039 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10040 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10041 .doit = wlan_hdd_cfg80211_ll_stats_set
10042 },
10043
10044 {
10045 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10046 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
10047 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10048 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10049 .doit = wlan_hdd_cfg80211_ll_stats_get
10050 },
10051#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
10052#ifdef FEATURE_WLAN_TDLS
10053 {
10054 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10055 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
10056 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10057 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10058 .doit = wlan_hdd_cfg80211_exttdls_enable
10059 },
10060 {
10061 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10062 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
10063 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10064 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10065 .doit = wlan_hdd_cfg80211_exttdls_disable
10066 },
10067 {
10068 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10069 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
10070 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
10071 .doit = wlan_hdd_cfg80211_exttdls_get_status
10072 },
10073#endif
10074 {
10075 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10076 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
10077 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
10078 .doit = wlan_hdd_cfg80211_get_supported_features
10079 },
10080 {
10081 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10082 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010083 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10084 WIPHY_VENDOR_CMD_NEED_NETDEV |
10085 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010086 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
10087 },
10088 {
10089 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10090 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
10091 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +053010092 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010093 },
10094 {
10095 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10096 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
10097 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010098 WIPHY_VENDOR_CMD_NEED_NETDEV |
10099 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010100 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
10101 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070010102 {
10103 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10104 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
10105 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010106 WIPHY_VENDOR_CMD_NEED_NETDEV |
10107 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070010108 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
10109 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010110 {
10111 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +053010112 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
10113 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10114 WIPHY_VENDOR_CMD_NEED_NETDEV |
10115 WIPHY_VENDOR_CMD_NEED_RUNNING,
10116 .doit = hdd_cfg80211_get_station_cmd
10117 },
10118 {
10119 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010120 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
10121 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10122 WIPHY_VENDOR_CMD_NEED_NETDEV |
10123 WIPHY_VENDOR_CMD_NEED_RUNNING,
10124 .doit = wlan_hdd_cfg80211_do_acs
10125 },
10126
10127 {
10128 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10129 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
10130 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10131 WIPHY_VENDOR_CMD_NEED_NETDEV,
10132 .doit = wlan_hdd_cfg80211_get_features
10133 },
10134#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10135 {
10136 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10137 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
10138 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10139 WIPHY_VENDOR_CMD_NEED_NETDEV |
10140 WIPHY_VENDOR_CMD_NEED_RUNNING,
10141 .doit = wlan_hdd_cfg80211_keymgmt_set_key
10142 },
10143#endif
10144#ifdef FEATURE_WLAN_EXTSCAN
10145 {
10146 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10147 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
10148 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10149 WIPHY_VENDOR_CMD_NEED_NETDEV |
10150 WIPHY_VENDOR_CMD_NEED_RUNNING,
10151 .doit = wlan_hdd_cfg80211_set_passpoint_list
10152 },
10153 {
10154 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10155 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
10156 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10157 WIPHY_VENDOR_CMD_NEED_NETDEV |
10158 WIPHY_VENDOR_CMD_NEED_RUNNING,
10159 .doit = wlan_hdd_cfg80211_reset_passpoint_list
10160 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010161#endif /* FEATURE_WLAN_EXTSCAN */
10162 {
10163 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10164 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
10165 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10166 WIPHY_VENDOR_CMD_NEED_NETDEV,
10167 .doit = wlan_hdd_cfg80211_get_wifi_info
10168 },
Paul Zhang3a210c52016-12-08 10:18:12 +080010169#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010170 {
10171 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10172 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
10173 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10174 WIPHY_VENDOR_CMD_NEED_NETDEV |
10175 WIPHY_VENDOR_CMD_NEED_RUNNING,
10176 .doit = wlan_hdd_cfg80211_wifi_configuration_set
10177 },
Paul Zhang3a210c52016-12-08 10:18:12 +080010178#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010179 {
10180 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10181 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
10182 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010183 WIPHY_VENDOR_CMD_NEED_NETDEV |
10184 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010185 .doit = wlan_hdd_cfg80211_set_ext_roam_params
10186 },
10187 {
10188 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10189 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
10190 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010191 WIPHY_VENDOR_CMD_NEED_NETDEV |
10192 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010193 .doit = wlan_hdd_cfg80211_wifi_logger_start
10194 },
10195 {
10196 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10197 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
10198 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010199 WIPHY_VENDOR_CMD_NEED_NETDEV |
10200 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010201 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
10202 },
10203 {
10204 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10205 .info.subcmd =
10206 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
10207 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10208 WIPHY_VENDOR_CMD_NEED_NETDEV |
10209 WIPHY_VENDOR_CMD_NEED_RUNNING,
10210 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
10211 },
10212 {
10213 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10214 .info.subcmd =
10215 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
10216 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10217 WIPHY_VENDOR_CMD_NEED_NETDEV |
10218 WIPHY_VENDOR_CMD_NEED_RUNNING,
10219 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
10220 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070010221#ifdef WLAN_FEATURE_TSF
10222 {
10223 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10224 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
10225 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10226 WIPHY_VENDOR_CMD_NEED_NETDEV |
10227 WIPHY_VENDOR_CMD_NEED_RUNNING,
10228 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
10229 },
10230#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010231#ifdef FEATURE_WLAN_TDLS
10232 {
10233 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10234 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
10235 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10236 WIPHY_VENDOR_CMD_NEED_NETDEV |
10237 WIPHY_VENDOR_CMD_NEED_RUNNING,
10238 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
10239 },
10240#endif
10241#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
10242 {
10243 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10244 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
10245 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10246 WIPHY_VENDOR_CMD_NEED_NETDEV |
10247 WIPHY_VENDOR_CMD_NEED_RUNNING,
10248 .doit = wlan_hdd_cfg80211_offloaded_packets
10249 },
10250#endif
10251 {
10252 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10253 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
10254 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10255 WIPHY_VENDOR_CMD_NEED_NETDEV |
10256 WIPHY_VENDOR_CMD_NEED_RUNNING,
10257 .doit = wlan_hdd_cfg80211_monitor_rssi
10258 },
10259 {
10260 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010261 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
10262 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10263 WIPHY_VENDOR_CMD_NEED_NETDEV |
10264 WIPHY_VENDOR_CMD_NEED_RUNNING,
10265 .doit = wlan_hdd_cfg80211_set_ns_offload
10266 },
10267 {
10268 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010269 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
10270 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10271 WIPHY_VENDOR_CMD_NEED_NETDEV |
10272 WIPHY_VENDOR_CMD_NEED_RUNNING,
10273 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
10274 },
10275#ifdef WLAN_FEATURE_MEMDUMP
10276 {
10277 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10278 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
10279 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10280 WIPHY_VENDOR_CMD_NEED_NETDEV |
10281 WIPHY_VENDOR_CMD_NEED_RUNNING,
10282 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
10283 },
10284#endif /* WLAN_FEATURE_MEMDUMP */
10285 {
10286 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10287 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
10288 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10289 WIPHY_VENDOR_CMD_NEED_NETDEV |
10290 WIPHY_VENDOR_CMD_NEED_RUNNING,
10291 .doit = wlan_hdd_cfg80211_vendor_scan
10292 },
10293
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053010294 /* Vendor abort scan */
10295 {
10296 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10297 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
10298 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10299 WIPHY_VENDOR_CMD_NEED_NETDEV |
10300 WIPHY_VENDOR_CMD_NEED_RUNNING,
10301 .doit = wlan_hdd_vendor_abort_scan
10302 },
10303
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010304 /* OCB commands */
10305 {
10306 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10307 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
10308 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10309 WIPHY_VENDOR_CMD_NEED_NETDEV |
10310 WIPHY_VENDOR_CMD_NEED_RUNNING,
10311 .doit = wlan_hdd_cfg80211_ocb_set_config
10312 },
10313 {
10314 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10315 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
10316 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10317 WIPHY_VENDOR_CMD_NEED_NETDEV |
10318 WIPHY_VENDOR_CMD_NEED_RUNNING,
10319 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
10320 },
10321 {
10322 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10323 .info.subcmd =
10324 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
10325 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10326 WIPHY_VENDOR_CMD_NEED_NETDEV |
10327 WIPHY_VENDOR_CMD_NEED_RUNNING,
10328 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
10329 },
10330 {
10331 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10332 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
10333 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10334 WIPHY_VENDOR_CMD_NEED_NETDEV |
10335 WIPHY_VENDOR_CMD_NEED_RUNNING,
10336 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
10337 },
10338 {
10339 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10340 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
10341 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10342 WIPHY_VENDOR_CMD_NEED_NETDEV |
10343 WIPHY_VENDOR_CMD_NEED_RUNNING,
10344 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
10345 },
10346 {
10347 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10348 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
10349 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10350 WIPHY_VENDOR_CMD_NEED_NETDEV |
10351 WIPHY_VENDOR_CMD_NEED_RUNNING,
10352 .doit = wlan_hdd_cfg80211_dcc_get_stats
10353 },
10354 {
10355 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10356 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
10357 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10358 WIPHY_VENDOR_CMD_NEED_NETDEV |
10359 WIPHY_VENDOR_CMD_NEED_RUNNING,
10360 .doit = wlan_hdd_cfg80211_dcc_clear_stats
10361 },
10362 {
10363 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10364 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
10365 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10366 WIPHY_VENDOR_CMD_NEED_NETDEV |
10367 WIPHY_VENDOR_CMD_NEED_RUNNING,
10368 .doit = wlan_hdd_cfg80211_dcc_update_ndl
10369 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010370 {
10371 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10372 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
10373 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10374 WIPHY_VENDOR_CMD_NEED_NETDEV |
10375 WIPHY_VENDOR_CMD_NEED_RUNNING,
10376 .doit = wlan_hdd_cfg80211_get_link_properties
10377 },
Peng Xu278d0122015-09-24 16:34:17 -070010378 {
Peng Xud2220962016-07-11 17:59:17 -070010379 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070010380 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
10381 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10382 WIPHY_VENDOR_CMD_NEED_NETDEV |
10383 WIPHY_VENDOR_CMD_NEED_RUNNING,
10384 .doit = wlan_hdd_cfg80211_set_ota_test
10385 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080010386#ifdef FEATURE_LFR_SUBNET_DETECTION
10387 {
10388 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10389 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
10390 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10391 WIPHY_VENDOR_CMD_NEED_NETDEV |
10392 WIPHY_VENDOR_CMD_NEED_RUNNING,
10393 .doit = wlan_hdd_cfg80211_set_gateway_params
10394 },
10395#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070010396 {
Peng Xud2220962016-07-11 17:59:17 -070010397 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070010398 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
10399 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10400 WIPHY_VENDOR_CMD_NEED_NETDEV |
10401 WIPHY_VENDOR_CMD_NEED_RUNNING,
10402 .doit = wlan_hdd_cfg80211_txpower_scale
10403 },
10404 {
10405 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10406 .info.subcmd =
10407 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
10408 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10409 WIPHY_VENDOR_CMD_NEED_NETDEV |
10410 WIPHY_VENDOR_CMD_NEED_RUNNING,
10411 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
10412 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010413 {
10414 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10415 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
10416 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10417 WIPHY_VENDOR_CMD_NEED_NETDEV |
10418 WIPHY_VENDOR_CMD_NEED_RUNNING,
10419 .doit = wlan_hdd_cfg80211_bpf_offload
10420 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010421 {
10422 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053010423 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
10424 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10425 WIPHY_VENDOR_CMD_NEED_NETDEV |
10426 WIPHY_VENDOR_CMD_NEED_RUNNING,
10427 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10428 },
10429 {
10430 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010431 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10432 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10433 WIPHY_VENDOR_CMD_NEED_NETDEV |
10434 WIPHY_VENDOR_CMD_NEED_RUNNING,
10435 .doit = wlan_hdd_cfg80211_sta_roam_policy
10436 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010437#ifdef FEATURE_WLAN_CH_AVOID
10438 {
10439 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10440 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10441 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10442 WIPHY_VENDOR_CMD_NEED_NETDEV |
10443 WIPHY_VENDOR_CMD_NEED_RUNNING,
10444 .doit = wlan_hdd_cfg80211_avoid_freq
10445 },
10446#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010447 {
10448 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010449 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10450 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10451 WIPHY_VENDOR_CMD_NEED_NETDEV |
10452 WIPHY_VENDOR_CMD_NEED_RUNNING,
10453 .doit = wlan_hdd_cfg80211_sap_configuration_set
10454 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010455 {
Peng Xu4225c152016-07-14 21:18:14 -070010456 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010457 .info.subcmd =
10458 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10459 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10460 WIPHY_VENDOR_CMD_NEED_NETDEV |
10461 WIPHY_VENDOR_CMD_NEED_RUNNING,
10462 .doit = wlan_hdd_cfg80211_p2p_lo_start
10463 },
10464 {
10465 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10466 .info.subcmd =
10467 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10468 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10469 WIPHY_VENDOR_CMD_NEED_NETDEV |
10470 WIPHY_VENDOR_CMD_NEED_RUNNING,
10471 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10472 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010473 {
10474 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10475 .info.subcmd =
10476 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10477 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10478 WIPHY_VENDOR_CMD_NEED_NETDEV |
10479 WIPHY_VENDOR_CMD_NEED_RUNNING,
10480 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10481 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010482#ifdef WLAN_FEATURE_NAN_DATAPATH
10483 {
10484 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10485 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10486 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10487 WIPHY_VENDOR_CMD_NEED_NETDEV |
10488 WIPHY_VENDOR_CMD_NEED_RUNNING,
10489 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10490 },
10491#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010492 {
10493 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10494 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10495 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10496 WIPHY_VENDOR_CMD_NEED_NETDEV |
10497 WIPHY_VENDOR_CMD_NEED_RUNNING,
10498 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10499 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010500 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010501 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10502 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10503 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10504 WIPHY_VENDOR_CMD_NEED_NETDEV |
10505 WIPHY_VENDOR_CMD_NEED_RUNNING,
10506 .doit = wlan_hdd_cfg80211_get_bus_size
10507 },
10508 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010509 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10510 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10511 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10512 WIPHY_VENDOR_CMD_NEED_NETDEV |
10513 WIPHY_VENDOR_CMD_NEED_RUNNING,
10514 .doit = wlan_hdd_cfg80211_update_vendor_channel
10515 },
10516 {
bingsd09dea32017-03-17 10:08:26 +080010517 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010518 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10519 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10520 WIPHY_VENDOR_CMD_NEED_NETDEV |
10521 WIPHY_VENDOR_CMD_NEED_RUNNING,
10522 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010523 },
10524 {
10525 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10526 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10527 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10528 WIPHY_VENDOR_CMD_NEED_NETDEV |
10529 WIPHY_VENDOR_CMD_NEED_RUNNING,
10530 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010531 },
10532#ifdef WLAN_FEATURE_DISA
10533 {
10534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10535 .info.subcmd =
10536 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10537 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10538 WIPHY_VENDOR_CMD_NEED_NETDEV |
10539 WIPHY_VENDOR_CMD_NEED_RUNNING,
10540 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10541 },
10542#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010543#ifdef FEATURE_WLAN_TDLS
10544 {
10545 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10546 .info.subcmd =
10547 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10548 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10549 WIPHY_VENDOR_CMD_NEED_NETDEV |
10550 WIPHY_VENDOR_CMD_NEED_RUNNING,
10551 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010552 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010553#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010554 {
10555 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10556 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10557 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10558 WIPHY_VENDOR_CMD_NEED_RUNNING,
10559 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10560 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010561 {
10562 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10563 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10564 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10565 WIPHY_VENDOR_CMD_NEED_NETDEV |
10566 WIPHY_VENDOR_CMD_NEED_RUNNING,
10567 .doit = wlan_hdd_cfg80211_set_trace_level
10568 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080010569 {
10570 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10571 .info.subcmd =
10572 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
10573 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10574 WIPHY_VENDOR_CMD_NEED_NETDEV |
10575 WIPHY_VENDOR_CMD_NEED_RUNNING,
10576 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
10577 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010578
Paul Zhang3a210c52016-12-08 10:18:12 +080010579#ifdef WLAN_UMAC_CONVERGENCE
10580 COMMON_VENDOR_COMMANDS
10581#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010582 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010583};
10584
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010585#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10586 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10587 defined(FEATURE_WLAN_SCAN_PNO)
10588/**
10589 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10590 * @wiphy: pointer to wiphy
10591 * @config: pointer to config
10592 *
10593 * Return: None
10594 */
10595static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10596 struct hdd_config *config)
10597{
10598 if (config->configPNOScanSupport) {
10599 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010600 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10601 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010602 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010603 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010604 if (config->max_sched_scan_plan_interval)
10605 wiphy->max_sched_scan_plan_interval =
10606 config->max_sched_scan_plan_interval;
10607 if (config->max_sched_scan_plan_iterations)
10608 wiphy->max_sched_scan_plan_iterations =
10609 config->max_sched_scan_plan_iterations;
10610 }
10611}
10612#else
10613static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10614 struct hdd_config *config)
10615{
10616}
10617#endif
10618
10619
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010620/**
10621 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10622 * @priv_size: Size of the hdd context.
10623 *
10624 * Allocate wiphy context and hdd context.
10625 *
10626 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010627 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010628hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010629{
10630 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010631 hdd_context_t *hdd_ctx;
10632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010633 ENTER();
10634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010635 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10636
10637 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010638 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010639 return NULL;
10640 }
10641
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010642 hdd_ctx = wiphy_priv(wiphy);
10643
10644 hdd_ctx->wiphy = wiphy;
10645
10646 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010647}
10648
10649/*
10650 * FUNCTION: wlan_hdd_cfg80211_update_band
10651 * This function is called from the supplicant through a
10652 * private ioctl to change the band value
10653 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010654int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10655 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010656{
10657 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010658 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010659
10660 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010661 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010662
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010663 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010664 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010665
10666 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10667 struct ieee80211_supported_band *band = wiphy->bands[i];
10668
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010669 channelEnabledState = wlan_reg_get_channel_state(
10670 hdd_ctx->hdd_pdev,
10671 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010672
Dustin Browna30892e2016-10-12 17:28:36 -070010673 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010674 /* 5G only */
10675#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10676 /* Enable Social channels for P2P */
10677 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10678 (band->channels[j].center_freq)
10679 && CHANNEL_STATE_ENABLE ==
10680 channelEnabledState)
10681 band->channels[j].flags &=
10682 ~IEEE80211_CHAN_DISABLED;
10683 else
10684#endif
10685 band->channels[j].flags |=
10686 IEEE80211_CHAN_DISABLED;
10687 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010688 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010689 eCSR_BAND_24 == eBand) {
10690 /* 2G only */
10691 band->channels[j].flags |=
10692 IEEE80211_CHAN_DISABLED;
10693 continue;
10694 }
10695
Amar Singhal6842e8f2016-02-23 16:30:32 -080010696 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697 band->channels[j].flags &=
10698 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010699 }
10700 }
10701 return 0;
10702}
10703
Peng Xuacfdda12017-02-06 16:15:38 -080010704#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010705/*
10706 * FUNCTION: wlan_hdd_cfg80211_init
10707 * This function is called by hdd_wlan_startup()
10708 * during initialization.
10709 * This function is used to initialize and register wiphy structure.
10710 */
10711int wlan_hdd_cfg80211_init(struct device *dev,
10712 struct wiphy *wiphy, struct hdd_config *pCfg)
10713{
10714 int i, j;
10715 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10716
10717 ENTER();
10718
10719 /* Now bind the underlying wlan device with wiphy */
10720 set_wiphy_dev(wiphy, dev);
10721
10722 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10723
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010724 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10725 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10726 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10727#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10728 | WIPHY_FLAG_4ADDR_STATION
10729#endif
10730 | WIPHY_FLAG_OFFCHAN_TX;
10731
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010732#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10733 wiphy->wowlan = &wowlan_support_cfg80211_init;
10734#else
10735 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10736 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10737 wiphy->wowlan.pattern_min_len = 1;
10738 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10739#endif
10740
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010741 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010742#ifdef FEATURE_WLAN_ESE
10743 || pCfg->isEseIniFeatureEnabled
10744#endif
10745 ) {
10746 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10747 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010748#ifdef FEATURE_WLAN_TDLS
10749 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10750 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10751#endif
10752
10753 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10754
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010755#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10756 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10757#endif
10758
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010759 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760
10761#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010762 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010763#endif
10764
10765 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010766 * driver can still register regulatory callback and
10767 * it will get regulatory settings in wiphy->band[], but
10768 * driver need to determine what to do with both
10769 * regulatory settings
10770 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010771
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010772#if defined QCA_WIFI_FTM
10773}
10774#endif
10775
10776 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10777
10778 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10779
10780 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10781
Arun Khandavallifae92942016-08-01 13:31:08 +053010782 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10783 | BIT(NL80211_IFTYPE_ADHOC)
10784 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10785 | BIT(NL80211_IFTYPE_P2P_GO)
10786 | BIT(NL80211_IFTYPE_AP)
10787 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788
Arun Khandavallifae92942016-08-01 13:31:08 +053010789 if (pCfg->advertiseConcurrentOperation) {
10790 if (pCfg->enableMCC) {
10791 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010792
Arun Khandavallifae92942016-08-01 13:31:08 +053010793 for (i = 0;
10794 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10795 i++) {
10796 if (!pCfg->allowMCCGODiffBI)
10797 wlan_hdd_iface_combination[i].
10798 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010799 }
10800 }
10801 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010802 ARRAY_SIZE(wlan_hdd_iface_combination);
10803 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010804 }
10805
10806 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010807 * on ini values
10808 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010809 if (!pCfg->ShortGI20MhzEnable) {
10810 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10811 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010812 }
10813
10814 if (!pCfg->ShortGI40MhzEnable) {
10815 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10816 }
10817
10818 if (!pCfg->nChannelBondingMode5GHz) {
10819 wlan_hdd_band_5_ghz.ht_cap.cap &=
10820 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10821 }
10822
Abhishek Singhf512bf32016-05-04 16:47:46 +053010823 /*
10824 * In case of static linked driver at the time of driver unload,
10825 * module exit doesn't happens. Module cleanup helps in cleaning
10826 * of static memory.
10827 * If driver load happens statically, at the time of driver unload,
10828 * wiphy flags don't get reset because of static memory.
10829 * It's better not to store channel in static memory.
10830 */
Dustin Browna30892e2016-10-12 17:28:36 -070010831 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10832 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010833 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010834 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010835 hdd_err("Not enough memory to allocate channels");
10836 return -ENOMEM;
10837 }
Dustin Browna30892e2016-10-12 17:28:36 -070010838 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010839 &hdd_channels_2_4_ghz[0],
10840 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010841 if ((hdd_is_5g_supported(pHddCtx)) &&
10842 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10843 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10844 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10845 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010846 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10847 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010848 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010849 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010850 hdd_err("Not enough memory to allocate channels");
10851 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010852 bands[NL80211_BAND_2GHZ]->channels);
10853 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010854 return -ENOMEM;
10855 }
Dustin Browna30892e2016-10-12 17:28:36 -070010856 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010857 &hdd_channels_5_ghz[0],
10858 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010859 }
10860
Dustin Browna30892e2016-10-12 17:28:36 -070010861 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010862
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010863 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010864 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010865
10866 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10867 struct ieee80211_supported_band *band = wiphy->bands[i];
10868
Dustin Browna30892e2016-10-12 17:28:36 -070010869 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010870 eCSR_BAND_5G == pCfg->nBandCapability) {
10871 /* 5G only */
10872#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10873 /* Enable social channels for P2P */
10874 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10875 (band->channels[j].center_freq))
10876 band->channels[j].flags &=
10877 ~IEEE80211_CHAN_DISABLED;
10878 else
10879#endif
10880 band->channels[j].flags |=
10881 IEEE80211_CHAN_DISABLED;
10882 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010883 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010884 eCSR_BAND_24 == pCfg->nBandCapability) {
10885 /* 2G only */
10886 band->channels[j].flags |=
10887 IEEE80211_CHAN_DISABLED;
10888 continue;
10889 }
10890 }
10891 }
10892 /*Initialise the supported cipher suite details */
10893 wiphy->cipher_suites = hdd_cipher_suites;
10894 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10895
10896 /*signal strength in mBm (100*dBm) */
10897 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10898 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10899
Anurag Chouhan6d760662016-02-20 16:05:43 +053010900 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010901 wiphy->n_vendor_commands =
10902 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10903 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10904
10905 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10906 wiphy->n_vendor_events =
10907 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10908 }
10909
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010910 if (pCfg->enableDFSMasterCap) {
10911 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10912 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010913
10914 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10915
10916#ifdef QCA_HT_2040_COEX
10917 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10918#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010919 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010920
10921#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10922 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10923 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10924 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10925 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10926#endif
10927
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010928 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010929 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010931 EXIT();
10932 return 0;
10933}
10934
Abhishek Singhf512bf32016-05-04 16:47:46 +053010935/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010936 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10937 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010938 *
10939 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010940 * memory allocated in wlan_hdd_cfg80211_init also
10941 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010942 *
10943 * Return: void
10944 */
10945void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10946{
10947 int i;
10948
Dustin Browna30892e2016-10-12 17:28:36 -070010949 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010950 if (NULL != wiphy->bands[i] &&
10951 (NULL != wiphy->bands[i]->channels)) {
10952 qdf_mem_free(wiphy->bands[i]->channels);
10953 wiphy->bands[i]->channels = NULL;
10954 }
10955 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010956
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010957 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010958}
10959
Yingying Tang80e15f32016-09-27 18:23:01 +080010960/**
10961 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10962 * @hdd_ctx: HDD context
10963 *
10964 * this function will update capabilities for supported bands
10965 *
10966 * Return: void
10967 */
10968static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10969{
10970 uint32_t val32;
10971 uint16_t val16;
10972 tSirMacHTCapabilityInfo *ht_cap_info;
10973 QDF_STATUS status;
10974
10975 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10976 if (QDF_STATUS_SUCCESS != status) {
10977 hdd_err("could not get HT capability info");
10978 val32 = 0;
10979 }
10980 val16 = (uint16_t)val32;
10981 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10982
10983 if (ht_cap_info->txSTBC == true) {
10984 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10985 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10986 IEEE80211_HT_CAP_TX_STBC;
10987 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10988 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10989 IEEE80211_HT_CAP_TX_STBC;
10990 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010991
10992 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10993 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10994 vht_cap.vht_supported = 0;
10995 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10996 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10997 vht_cap.vht_supported = 0;
10998 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10999 }
Yingying Tang80e15f32016-09-27 18:23:01 +080011000}
11001
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011003 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011004 * initialization. In wlan_hdd_cfg80211_init, only the
11005 * default values will be initialized. The final initialization
11006 * of all required members can be done here.
11007 */
Yingying Tang80e15f32016-09-27 18:23:01 +080011008void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011009{
Yingying Tang80e15f32016-09-27 18:23:01 +080011010 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
11011
11012 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011013}
11014
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011015/**
11016 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
11017 * @cfg: hdd cfg
11018 *
11019 * this function update 11n mode in hdd cfg
11020 *
11021 * Return: void
11022 */
11023void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
11024{
11025 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011026 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011027 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011028 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011029 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
11030 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
11031 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
11032 cfg->sap_p2p_11ac_override = 0;
11033 }
11034 }
11035}
11036
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011037/* In this function we are registering wiphy. */
11038int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
11039{
11040 ENTER();
11041 /* Register our wiphy dev with cfg80211 */
11042 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011043 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011044 return -EIO;
11045 }
11046
11047 EXIT();
11048 return 0;
11049}
11050
11051/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011052 * HDD function to update wiphy capability based on target offload status.
11053 *
11054 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
11055 * capability even before downloading firmware to the target. In discrete
11056 * case, host will get know certain offload capability (say sched_scan
11057 * caps) only after downloading firmware to the target and target boots up.
11058 * This function is used to override setting done in wlan_hdd_cfg80211_init()
11059 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011060 */
11061void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
11062{
11063#ifdef FEATURE_WLAN_SCAN_PNO
11064 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
11065 struct hdd_config *pCfg = pHddCtx->config;
11066
11067 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
11068 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011069 * have PNO support.
11070 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011071 if (!pCfg->PnoOffload) {
11072 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
11073 wiphy->max_sched_scan_ssids = 0;
11074 wiphy->max_match_sets = 0;
11075 wiphy->max_sched_scan_ie_len = 0;
11076 }
11077#endif
11078}
11079
11080/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011081#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
11082
Wu Gao84d120c2017-03-24 18:46:00 +080011083void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
11084{
11085 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11086 /* Register for all P2P action, public action etc frames */
11087 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11088
11089 ENTER();
11090
11091 /* Register frame indication call back */
11092 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
11093
11094 /* Register for p2p ack indication */
11095 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
11096
11097 /* Right now we are registering these frame when driver is getting
11098 * initialized. Once we will move to 2.6.37 kernel, in which we have
11099 * frame register ops, we will move this code as a part of that
11100 */
11101
11102 /* GAS Initial Request */
11103 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11104 (uint8_t *) GAS_INITIAL_REQ,
11105 GAS_INITIAL_REQ_SIZE);
11106
11107 /* GAS Initial Response */
11108 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11109 (uint8_t *) GAS_INITIAL_RSP,
11110 GAS_INITIAL_RSP_SIZE);
11111
11112 /* GAS Comeback Request */
11113 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11114 (uint8_t *) GAS_COMEBACK_REQ,
11115 GAS_COMEBACK_REQ_SIZE);
11116
11117 /* GAS Comeback Response */
11118 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11119 (uint8_t *) GAS_COMEBACK_RSP,
11120 GAS_COMEBACK_RSP_SIZE);
11121
11122 /* WNM BSS Transition Request frame */
11123 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11124 (uint8_t *) WNM_BSS_ACTION_FRAME,
11125 WNM_BSS_ACTION_FRAME_SIZE);
11126
11127 /* WNM-Notification */
11128 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
11129 (uint8_t *) WNM_NOTIFICATION_FRAME,
11130 WNM_NOTIFICATION_FRAME_SIZE);
11131}
11132#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011133void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
11134{
11135 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11136 /* Register for all P2P action, public action etc frames */
11137 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11138
11139 ENTER();
11140
Abhishek Singh7996eb72015-12-30 17:24:02 +053011141 /* Register frame indication call back */
11142 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
11143
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053011144 /* Register for p2p ack indication */
11145 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
11146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011147 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011148 * initialized. Once we will move to 2.6.37 kernel, in which we have
11149 * frame register ops, we will move this code as a part of that
11150 */
11151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152 /* GAS Initial Request */
11153 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11154 (uint8_t *) GAS_INITIAL_REQ,
11155 GAS_INITIAL_REQ_SIZE);
11156
11157 /* GAS Initial Response */
11158 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11159 (uint8_t *) GAS_INITIAL_RSP,
11160 GAS_INITIAL_RSP_SIZE);
11161
11162 /* GAS Comeback Request */
11163 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11164 (uint8_t *) GAS_COMEBACK_REQ,
11165 GAS_COMEBACK_REQ_SIZE);
11166
11167 /* GAS Comeback Response */
11168 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11169 (uint8_t *) GAS_COMEBACK_RSP,
11170 GAS_COMEBACK_RSP_SIZE);
11171
11172 /* P2P Public Action */
11173 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11174 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11175 P2P_PUBLIC_ACTION_FRAME_SIZE);
11176
11177 /* P2P Action */
11178 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11179 (uint8_t *) P2P_ACTION_FRAME,
11180 P2P_ACTION_FRAME_SIZE);
11181
11182 /* WNM BSS Transition Request frame */
11183 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11184 (uint8_t *) WNM_BSS_ACTION_FRAME,
11185 WNM_BSS_ACTION_FRAME_SIZE);
11186
11187 /* WNM-Notification */
11188 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
11189 (uint8_t *) WNM_NOTIFICATION_FRAME,
11190 WNM_NOTIFICATION_FRAME_SIZE);
11191}
Wu Gao84d120c2017-03-24 18:46:00 +080011192#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011193
11194void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
11195{
11196 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11197 /* Register for all P2P action, public action etc frames */
11198 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11199
11200 ENTER();
11201
11202 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011203 * initialized. Once we will move to 2.6.37 kernel, in which we have
11204 * frame register ops, we will move this code as a part of that
11205 */
11206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011207 /* GAS Initial Request */
11208
11209 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11210 (uint8_t *) GAS_INITIAL_REQ,
11211 GAS_INITIAL_REQ_SIZE);
11212
11213 /* GAS Initial Response */
11214 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11215 (uint8_t *) GAS_INITIAL_RSP,
11216 GAS_INITIAL_RSP_SIZE);
11217
11218 /* GAS Comeback Request */
11219 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11220 (uint8_t *) GAS_COMEBACK_REQ,
11221 GAS_COMEBACK_REQ_SIZE);
11222
11223 /* GAS Comeback Response */
11224 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11225 (uint8_t *) GAS_COMEBACK_RSP,
11226 GAS_COMEBACK_RSP_SIZE);
11227
11228 /* P2P Public Action */
11229 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11230 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11231 P2P_PUBLIC_ACTION_FRAME_SIZE);
11232
11233 /* P2P Action */
11234 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11235 (uint8_t *) P2P_ACTION_FRAME,
11236 P2P_ACTION_FRAME_SIZE);
11237
11238 /* WNM-Notification */
11239 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
11240 (uint8_t *) WNM_NOTIFICATION_FRAME,
11241 WNM_NOTIFICATION_FRAME_SIZE);
11242}
11243
11244#ifdef FEATURE_WLAN_WAPI
11245void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
11246 const uint8_t *mac_addr, const uint8_t *key,
11247 int key_Len)
11248{
11249 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11250 tCsrRoamSetKey setKey;
11251 bool isConnected = true;
11252 int status = 0;
11253 uint32_t roamId = 0xFF;
11254 uint8_t *pKeyPtr = NULL;
11255 int n = 0;
11256
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011257 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258 hdd_device_mode_to_string(pAdapter->device_mode),
11259 pAdapter->device_mode);
11260
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011261 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262 setKey.keyId = key_index; /* Store Key ID */
11263 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
11264 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
11265 setKey.paeRole = 0; /* the PAE role */
11266 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053011267 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011268 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011269 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270 }
11271 setKey.keyLength = key_Len;
11272 pKeyPtr = setKey.Key;
11273 memcpy(pKeyPtr, key, key_Len);
11274
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011275 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011276 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011277 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070011278 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011279
11280 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11281 if (isConnected) {
11282 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11283 pAdapter->sessionId, &setKey, &roamId);
11284 }
11285 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011286 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
11288 }
11289}
11290#endif /* FEATURE_WLAN_WAPI */
11291
11292uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
11293 uint8_t eid)
11294{
11295 int left = length;
11296 uint8_t *ptr = (uint8_t *)ies_ptr;
11297 uint8_t elem_id, elem_len;
11298
11299 while (left >= 2) {
11300 elem_id = ptr[0];
11301 elem_len = ptr[1];
11302 left -= 2;
11303 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011304 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011305 eid, elem_len, left);
11306 return NULL;
11307 }
11308 if (elem_id == eid) {
11309 return ptr;
11310 }
11311
11312 left -= elem_len;
11313 ptr += (elem_len + 2);
11314 }
11315 return NULL;
11316}
11317
Krunal Soni364e0872017-05-10 21:24:34 -070011318bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
11319{
11320 uint8_t *vendor_ie;
11321
11322 if (length < 2) {
11323 hdd_debug("bss size is less than expected");
11324 return true;
11325 }
11326 if (!ies) {
11327 hdd_debug("invalid IE pointer");
11328 return true;
11329 }
11330 vendor_ie = wlan_hdd_get_vendor_oui_ie_ptr(VENDOR1_AP_OUI_TYPE,
11331 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
11332 if (vendor_ie) {
11333 hdd_debug("AP can't support immediate powersave. defer it");
11334 return false;
11335 }
11336 return true;
11337}
11338
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339/*
11340 * FUNCTION: wlan_hdd_validate_operation_channel
11341 * called by wlan_hdd_cfg80211_start_bss() and
11342 * wlan_hdd_set_channel()
11343 * This function validates whether given channel is part of valid
11344 * channel list.
11345 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011346QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011347 int channel)
11348{
11349
11350 uint32_t num_ch = 0;
11351 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11352 u32 indx = 0;
11353 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11354 uint8_t fValidChannel = false, count = 0;
11355 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
11356
11357 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11358
11359 if (hdd_pConfig_ini->sapAllowAllChannel) {
11360 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080011361 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011362 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011363 fValidChannel = true;
11364 break;
11365 }
11366 }
11367 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011368 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011369 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 }
11371 } else {
11372 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
11373 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011374 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011375 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011376 }
11377 for (indx = 0; indx < num_ch; indx++) {
11378 if (channel == valid_ch[indx]) {
11379 break;
11380 }
11381 }
11382
11383 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011384 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011385 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011386 }
11387 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011388 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011389
11390}
11391
11392#ifdef DHCP_SERVER_OFFLOAD
11393static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
11394{
11395 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
11396 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
11397 uint8_t numEntries = 0;
11398 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
11399 uint8_t num;
11400 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011401 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011402 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070011403 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011404 return;
11405 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
11407 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
11408 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
11409 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
11410 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
11411 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011412 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011413 goto end;
11414 }
11415 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011416 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011417 goto end;
11418 }
11419 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011420 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011421 goto end;
11422 }
11423 for (num = 0; num < numEntries; num++) {
11424 temp = srv_ip[num];
11425 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
11426 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011427 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011428 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011429 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011430 goto end;
11431 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011432 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011433end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011434 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011435 return;
11436}
11437#endif /* DHCP_SERVER_OFFLOAD */
11438
11439static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11440 struct net_device *dev,
11441 struct bss_parameters *params)
11442{
11443 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11444 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11445 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011446 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011447
11448 ENTER();
11449
Anurag Chouhan6d760662016-02-20 16:05:43 +053011450 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011451 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011452 return -EINVAL;
11453 }
11454
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011455 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11456 hdd_err("invalid session id: %d", pAdapter->sessionId);
11457 return -EINVAL;
11458 }
11459
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011460 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11462 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011463 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011464 hdd_device_mode_to_string(pAdapter->device_mode),
11465 pAdapter->device_mode, params->ap_isolate);
11466
11467 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11468 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011469 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011470 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011471
Krunal Sonib4326f22016-03-10 13:05:51 -080011472 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11473 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011474 return -EOPNOTSUPP;
11475 }
11476
11477 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011478 * want to update this parameter
11479 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011480 if (-1 != params->ap_isolate) {
11481 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11482 !!params->ap_isolate;
11483
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011484 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011485 pAdapter->sessionId,
11486 pAdapter->sessionCtx.
11487 ap.
11488 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011489 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011490 ret = -EINVAL;
11491 }
11492 }
11493
11494 EXIT();
11495 return ret;
11496}
11497
Krunal Soni8c37e322016-02-03 16:08:37 -080011498/**
11499 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11500 * @ndev: pointer to net device provided by supplicant
11501 * @type: type of the interface, upper layer wanted to change
11502 *
11503 * Upper layer provides the new interface mode that needs to be changed
11504 * for given net device
11505 *
11506 * Return: success or failure in terms of integer value
11507 */
11508static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011509 enum nl80211_iftype type)
11510{
Krunal Soni8c37e322016-02-03 16:08:37 -080011511 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11512 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11513 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011514 hdd_wext_state_t *wext;
11515 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011516 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011517
11518 ENTER();
11519
Krunal Soni8c37e322016-02-03 16:08:37 -080011520 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011521 hdd_warn("ACS is in progress, don't change iface!");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011522 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011523 }
11524
11525 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011526 hdd_stop_adapter(hdd_ctx, adapter, true);
11527 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011528 wdev->iftype = type;
11529 /*Check for sub-string p2p to confirm its a p2p interface */
11530 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011531 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011532 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011533 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011534 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011535 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011536 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011537 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011539 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011540 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011541 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11542 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011543 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11544 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011546 adapter->scan_info.scanAddIE.length;
11547 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011548 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011549 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11550 wext->roamProfile.phyMode =
11551 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11552 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011553 EXIT();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011554
11555 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011556}
11557
11558static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11559 struct net_device *dev,
11560 struct bss_parameters *params)
11561{
11562 int ret;
11563
11564 cds_ssr_protect(__func__);
11565 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11566 cds_ssr_unprotect(__func__);
11567
11568 return ret;
11569}
11570
11571/* FUNCTION: wlan_hdd_change_country_code_cd
11572 * to wait for contry code completion
11573 */
11574void *wlan_hdd_change_country_code_cb(void *pAdapter)
11575{
11576 hdd_adapter_t *call_back_pAdapter = pAdapter;
11577 complete(&call_back_pAdapter->change_country_code);
11578 return NULL;
11579}
11580
Rajeev Kumar98edb772016-01-19 12:42:19 -080011581/**
11582 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11583 * @wiphy: Pointer to the wiphy structure
11584 * @ndev: Pointer to the net device
11585 * @type: Interface type
11586 * @flags: Flags for change interface
11587 * @params: Pointer to change interface parameters
11588 *
11589 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011590 */
11591static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11592 struct net_device *ndev,
11593 enum nl80211_iftype type,
11594 u32 *flags,
11595 struct vif_params *params)
11596{
11597 struct wireless_dev *wdev;
11598 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11599 hdd_context_t *pHddCtx;
11600 tCsrRoamProfile *pRoamProfile = NULL;
11601 eCsrRoamBssType LastBSSType;
11602 struct hdd_config *pConfig = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011603 int status;
11604
11605 ENTER();
11606
Anurag Chouhan6d760662016-02-20 16:05:43 +053011607 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011608 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609 return -EINVAL;
11610 }
11611
11612 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11613 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011614 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011615 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011616
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011617 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011618 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11619 pAdapter->sessionId, type));
11620
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011621 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011622 pAdapter->device_mode, type);
11623
Arun Khandavallifae92942016-08-01 13:31:08 +053011624 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11625 if (status) {
11626 hdd_err("Failed to start modules");
11627 return -EINVAL;
11628 }
11629
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011630 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011631 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11632 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011633 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011634 return -EINVAL;
11635 }
11636
11637 pConfig = pHddCtx->config;
11638 wdev = ndev->ieee80211_ptr;
11639
11640 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011641 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11642 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011643
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011644 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011645 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011646 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11647 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11648 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11649 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011650 hdd_wext_state_t *pWextState =
11651 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11652
11653 pRoamProfile = &pWextState->roamProfile;
11654 LastBSSType = pRoamProfile->BSSType;
11655
11656 switch (type) {
11657 case NL80211_IFTYPE_STATION:
11658 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011659 case NL80211_IFTYPE_ADHOC:
11660 if (type == NL80211_IFTYPE_ADHOC) {
11661 wlan_hdd_tdls_exit(pAdapter);
11662 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011663 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011664 }
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011665 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
Krunal Soni8c37e322016-02-03 16:08:37 -080011666 type);
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011667 if (status) {
11668 hdd_err("Failed to change iface to new mode:%d status %d",
11669 type, status);
11670 return status;
11671 }
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011672 if (hdd_start_adapter(pAdapter)) {
11673 hdd_err("Failed to start adapter :%d",
11674 pAdapter->device_mode);
11675 return -EINVAL;
11676 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011677 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011678 case NL80211_IFTYPE_AP:
11679 case NL80211_IFTYPE_P2P_GO:
11680 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011681 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011682 (type ==
11683 NL80211_IFTYPE_AP) ? "SoftAP" :
11684 "P2pGo");
11685
11686 /* Cancel any remain on channel for GO mode */
11687 if (NL80211_IFTYPE_P2P_GO == type) {
11688 wlan_hdd_cancel_existing_remain_on_channel
11689 (pAdapter);
11690 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691
Arun Khandavallifae92942016-08-01 13:31:08 +053011692 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 /* De-init the adapter */
11694 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11695 memset(&pAdapter->sessionCtx, 0,
11696 sizeof(pAdapter->sessionCtx));
11697 pAdapter->device_mode =
11698 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011699 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11700 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011701
11702 /*
11703 * Fw will take care incase of concurrency
11704 */
11705
Krunal Sonib4326f22016-03-10 13:05:51 -080011706 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011707 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011708 /* To meet Android requirements create
11709 * a randomized MAC address of the
11710 * form 02:1A:11:Fx:xx:xx
11711 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011712 get_random_bytes(&ndev->dev_addr[3], 3);
11713 ndev->dev_addr[0] = 0x02;
11714 ndev->dev_addr[1] = 0x1A;
11715 ndev->dev_addr[2] = 0x11;
11716 ndev->dev_addr[3] |= 0xF0;
11717 memcpy(pAdapter->macAddressCurrent.
11718 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011719 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011720 pr_info("wlan: Generated HotSpot BSSID "
11721 MAC_ADDRESS_STR "\n",
11722 MAC_ADDR_ARRAY(ndev->dev_addr));
11723 }
11724
11725 hdd_set_ap_ops(pAdapter->dev);
11726
Arun Khandavallifae92942016-08-01 13:31:08 +053011727 if (hdd_start_adapter(pAdapter)) {
11728 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011729 return -EINVAL;
11730 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011731 /* Interface type changed update in wiphy structure */
11732 if (wdev) {
11733 wdev->iftype = type;
11734 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011735 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011736 return -EINVAL;
11737 }
11738 goto done;
11739 }
11740
11741 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011742 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011743 return -EOPNOTSUPP;
11744 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011745 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11746 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011747 switch (type) {
11748 case NL80211_IFTYPE_STATION:
11749 case NL80211_IFTYPE_P2P_CLIENT:
11750 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011751 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11752 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011753 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011754 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011755 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011756 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011757 pAdapter->device_mode);
11758 return -EINVAL;
11759 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011760 goto done;
11761
11762 case NL80211_IFTYPE_AP:
11763 case NL80211_IFTYPE_P2P_GO:
11764 wdev->iftype = type;
11765 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011766 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011767 goto done;
11768
11769 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011770 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011771 return -EOPNOTSUPP;
11772 }
11773 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011774 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011775 pAdapter->device_mode);
11776 return -EOPNOTSUPP;
11777 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011778done:
11779 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011780 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11781 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011782
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011783 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784
11785 EXIT();
11786 return 0;
11787}
11788
Rajeev Kumar98edb772016-01-19 12:42:19 -080011789/**
11790 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11791 * @wiphy: Pointer to the wiphy structure
11792 * @ndev: Pointer to the net device
11793 * @type: Interface type
11794 * @flags: Flags for change interface
11795 * @params: Pointer to change interface parameters
11796 *
11797 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011798 */
11799static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11800 struct net_device *ndev,
11801 enum nl80211_iftype type,
11802 u32 *flags,
11803 struct vif_params *params)
11804{
11805 int ret;
11806
11807 cds_ssr_protect(__func__);
11808 ret =
11809 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11810 cds_ssr_unprotect(__func__);
11811
11812 return ret;
11813}
11814
Frank Liud4b2fa02017-03-29 11:46:48 +080011815#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011816static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11817 int index, uint8_t match)
11818{
11819 int i;
11820 for (i = 0; i < index; i++) {
11821 if (arr[i] == match)
11822 return true;
11823 }
11824 return false;
11825}
11826#endif
11827
11828/**
11829 * __wlan_hdd_change_station() - change station
11830 * @wiphy: Pointer to the wiphy structure
11831 * @dev: Pointer to the net device.
11832 * @mac: bssid
11833 * @params: Pointer to station parameters
11834 *
11835 * Return: 0 for success, error number on failure.
11836 */
11837#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11838static int __wlan_hdd_change_station(struct wiphy *wiphy,
11839 struct net_device *dev,
11840 const uint8_t *mac,
11841 struct station_parameters *params)
11842#else
11843static int __wlan_hdd_change_station(struct wiphy *wiphy,
11844 struct net_device *dev,
11845 uint8_t *mac,
11846 struct station_parameters *params)
11847#endif
11848{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011849 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011850 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11851 hdd_context_t *pHddCtx;
11852 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011853 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011854#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011855 tCsrStaParams StaParams = { 0 };
11856 uint8_t isBufSta = 0;
11857 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011858 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011859#endif
11860 int ret;
11861
11862 ENTER();
11863
Anurag Chouhan6d760662016-02-20 16:05:43 +053011864 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011865 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011866 return -EINVAL;
11867 }
11868
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011869 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011870 TRACE_CODE_HDD_CHANGE_STATION,
11871 pAdapter->sessionId, params->listen_interval));
11872
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011873 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11874 hdd_err("invalid session id: %d", pAdapter->sessionId);
11875 return -EINVAL;
11876 }
11877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011878 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11879 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011880 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011881 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011882
11883 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11884
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011885 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011886
Krunal Sonib4326f22016-03-10 13:05:51 -080011887 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11888 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011889 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11890 status =
11891 hdd_softap_change_sta_state(pAdapter,
11892 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011893 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011894
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011895 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011896 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011897 return -EINVAL;
11898 }
11899 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011900 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11901 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011902 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011903#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11904 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11905 dev, mac, params);
11906#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011907
11908 if (cds_is_sub_20_mhz_enabled()) {
11909 hdd_err("TDLS not allowed with sub 20 MHz");
11910 return -EINVAL;
11911 }
11912
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011913 StaParams.capability = params->capability;
11914 StaParams.uapsd_queues = params->uapsd_queues;
11915 StaParams.max_sp = params->max_sp;
11916
11917 /* Convert (first channel , number of channels) tuple to
11918 * the total list of channels. This goes with the assumption
11919 * that if the first channel is < 14, then the next channels
11920 * are an incremental of 1 else an incremental of 4 till the number
11921 * of channels.
11922 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011923 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011924 if (0 != params->supported_channels_len) {
11925 int i = 0, j = 0, k = 0, no_of_channels = 0;
11926 int num_unique_channels;
11927 int next;
11928 for (i = 0;
11929 i < params->supported_channels_len
11930 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11931 int wifi_chan_index;
11932 if (!wlan_hdd_is_duplicate_channel
11933 (StaParams.supported_channels, j,
11934 params->supported_channels[i])) {
11935 StaParams.
11936 supported_channels[j] =
11937 params->
11938 supported_channels[i];
11939 } else {
11940 continue;
11941 }
11942 wifi_chan_index =
11943 ((StaParams.supported_channels[j] <=
11944 HDD_CHANNEL_14) ? 1 : 4);
11945 no_of_channels =
11946 params->supported_channels[i + 1];
11947
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011948 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 -080011949 StaParams.
11950 supported_channels[j],
11951 wifi_chan_index,
11952 no_of_channels);
11953 for (k = 1; k <= no_of_channels &&
11954 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11955 k++) {
11956 next =
11957 StaParams.
11958 supported_channels[j] +
11959 wifi_chan_index;
11960 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11961 StaParams.
11962 supported_channels[j
11963 +
11964 1]
11965 = next;
11966 } else {
11967 continue;
11968 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011969 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011970 j + 1,
11971 StaParams.
11972 supported_channels[j +
11973 1]);
11974 j += 1;
11975 }
11976 }
11977 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011978 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011979 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011980 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011981 StaParams.
11982 supported_channels[i]);
11983 }
11984 if (MAX_CHANNEL < num_unique_channels)
11985 num_unique_channels = MAX_CHANNEL;
11986 StaParams.supported_channels_len =
11987 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011988 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011989 StaParams.supported_channels_len);
11990 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011991 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011992 params->supported_oper_classes,
11993 params->supported_oper_classes_len);
11994 StaParams.supported_oper_classes_len =
11995 params->supported_oper_classes_len;
11996
11997 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011998 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011999 params->ext_capab,
12000 sizeof(StaParams.extn_capability));
12001
12002 if (NULL != params->ht_capa) {
12003 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012004 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012005 sizeof(tSirHTCap));
12006 }
12007
12008 StaParams.supported_rates_len =
12009 params->supported_rates_len;
12010
12011 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
12012 * The supported_rates array , for all the structures propogating till Add Sta
12013 * to the firmware has to be modified , if the supplicant (ieee80211) is
12014 * modified to send more rates.
12015 */
12016
12017 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
12018 */
12019 if (StaParams.supported_rates_len >
12020 SIR_MAC_MAX_SUPP_RATES)
12021 StaParams.supported_rates_len =
12022 SIR_MAC_MAX_SUPP_RATES;
12023
12024 if (0 != StaParams.supported_rates_len) {
12025 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012026 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012027 params->supported_rates,
12028 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012029 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012030 StaParams.supported_rates_len);
12031 for (i = 0; i < StaParams.supported_rates_len;
12032 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012033 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012034 StaParams.supported_rates[i]);
12035 }
12036
12037 if (NULL != params->vht_capa) {
12038 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012039 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012040 params->vht_capa,
12041 sizeof(tSirVHTCap));
12042 }
12043
12044 if (0 != params->ext_capab_len) {
12045 /*Define A Macro : TODO Sunil */
12046 if ((1 << 4) & StaParams.extn_capability[3]) {
12047 isBufSta = 1;
12048 }
12049 /* TDLS Channel Switching Support */
12050 if ((1 << 6) & StaParams.extn_capability[3]) {
12051 isOffChannelSupported = 1;
12052 }
12053 }
12054
Nitesh Shah99934ac2016-09-05 15:54:08 +053012055 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053012056 (params->ht_capa || params->vht_capa ||
12057 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053012058 is_qos_wmm_sta = true;
12059
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012060 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053012061 " is_qos_wmm_sta= %d HTcapPresent = %d",
12062 __func__, is_qos_wmm_sta,
12063 StaParams.htcap_present);
12064
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012065 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053012066 &StaParams,
12067 isBufSta,
12068 isOffChannelSupported,
12069 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012070 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012071 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012072 return -EINVAL;
12073 }
12074
12075 status =
12076 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
12077 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012078 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012079 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012080 return -EINVAL;
12081 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012082#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080012083 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012084 }
12085 EXIT();
12086 return ret;
12087}
12088
12089/**
12090 * wlan_hdd_change_station() - cfg80211 change station handler function
12091 * @wiphy: Pointer to the wiphy structure
12092 * @dev: Pointer to the net device.
12093 * @mac: bssid
12094 * @params: Pointer to station parameters
12095 *
12096 * This is the cfg80211 change station handler function which invokes
12097 * the internal function @__wlan_hdd_change_station with
12098 * SSR protection.
12099 *
12100 * Return: 0 for success, error number on failure.
12101 */
12102#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
12103static int wlan_hdd_change_station(struct wiphy *wiphy,
12104 struct net_device *dev,
12105 const u8 *mac,
12106 struct station_parameters *params)
12107#else
12108static int wlan_hdd_change_station(struct wiphy *wiphy,
12109 struct net_device *dev,
12110 u8 *mac,
12111 struct station_parameters *params)
12112#endif
12113{
12114 int ret;
12115
12116 cds_ssr_protect(__func__);
12117 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
12118 cds_ssr_unprotect(__func__);
12119
12120 return ret;
12121}
12122
12123/*
12124 * FUNCTION: __wlan_hdd_cfg80211_add_key
12125 * This function is used to initialize the key information
12126 */
12127static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12128 struct net_device *ndev,
12129 u8 key_index, bool pairwise,
12130 const u8 *mac_addr,
12131 struct key_params *params)
12132{
12133 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12134 tCsrRoamSetKey setKey;
12135 int status;
12136 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012137 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012138 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012139 hdd_context_t *pHddCtx;
12140 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12141
12142 ENTER();
12143
Anurag Chouhan6d760662016-02-20 16:05:43 +053012144 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012145 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012146 return -EINVAL;
12147 }
12148
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012149 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012150 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012151 return -EINVAL;
12152 }
12153
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012154 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012155 TRACE_CODE_HDD_CFG80211_ADD_KEY,
12156 pAdapter->sessionId, params->key_len));
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
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012163 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012164 hdd_device_mode_to_string(pAdapter->device_mode),
12165 pAdapter->device_mode);
12166
12167 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012168 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012169
12170 return -EINVAL;
12171 }
12172
12173 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012174 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012175
12176 return -EINVAL;
12177 }
12178
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012179 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012180
12181 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012182 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012183 setKey.keyId = key_index;
12184 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012185 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012186
12187 switch (params->cipher) {
12188 case WLAN_CIPHER_SUITE_WEP40:
12189 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12190 break;
12191
12192 case WLAN_CIPHER_SUITE_WEP104:
12193 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
12194 break;
12195
12196 case WLAN_CIPHER_SUITE_TKIP:
12197 {
12198 u8 *pKey = &setKey.Key[0];
12199 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
12200
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012201 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012202
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012203 /* Supplicant sends the 32bytes key in this order
12204 *
12205 * |--------------|----------|----------|
12206 * | Tk1 |TX-MIC | RX Mic |
12207 * |--------------|----------|----------|
12208 * <---16bytes---><--8bytes--><--8bytes-->
12209 *
12210 * Sme expects the 32 bytes key to be in the below order
12211 *
12212 * |--------------|----------|----------|
12213 * | Tk1 |RX-MIC | TX Mic |
12214 * |--------------|----------|----------|
12215 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012216 */
12217 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012218 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012219
12220 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012221 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012222
12223 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012224 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012225
12226 break;
12227 }
12228
12229 case WLAN_CIPHER_SUITE_CCMP:
12230 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
12231 break;
12232
12233#ifdef FEATURE_WLAN_WAPI
12234 case WLAN_CIPHER_SUITE_SMS4:
12235 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012236 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012237 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
12238 mac_addr, params->key,
12239 params->key_len);
12240 return 0;
12241 }
12242#endif
12243
12244#ifdef FEATURE_WLAN_ESE
12245 case WLAN_CIPHER_SUITE_KRK:
12246 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
12247 break;
12248#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12249 case WLAN_CIPHER_SUITE_BTK:
12250 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
12251 break;
12252#endif
12253#endif
12254
12255#ifdef WLAN_FEATURE_11W
12256 case WLAN_CIPHER_SUITE_AES_CMAC:
12257 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
12258 break;
12259#endif
12260
12261 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012262 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012263 return -EOPNOTSUPP;
12264 }
12265
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012266 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012267
12268 if (!pairwise) {
12269 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012270 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012271 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012272 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012273 } else {
12274 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012275 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012276 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012277 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012279 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012280 /* if a key is already installed, block all subsequent ones */
12281 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012282 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012283 return 0;
12284 }
12285
12286 setKey.keyDirection = eSIR_TX_RX;
12287 /*Set the group key */
12288 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12289 pAdapter->sessionId, &setKey, &roamId);
12290
12291 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012292 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012293 return -EINVAL;
12294 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012295 /* Save the keys here and call sme_roam_set_key for setting
12296 * the PTK after peer joins the IBSS network
12297 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012298 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012299 &setKey, sizeof(tCsrRoamSetKey));
12300
12301 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
12302 return status;
12303 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012304 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
12305 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012306 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
12307 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070012308 status = wlansap_set_key_sta(
12309 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012310 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012311 hdd_err("wlansap_set_key_sta failed status: %d",
12312 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012313 }
12314 }
12315
12316 /* Save the key in ap ctx for use on START_BASS and restart */
12317 if (pairwise ||
12318 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
12319 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012320 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012321 sizeof(tCsrRoamSetKey));
12322 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012323 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324 sizeof(tCsrRoamSetKey));
12325
Krunal Sonib4326f22016-03-10 13:05:51 -080012326 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
12327 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012328 hdd_wext_state_t *pWextState =
12329 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12330 hdd_station_ctx_t *pHddStaCtx =
12331 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12332
12333 if (!pairwise) {
12334 /* set group key */
12335 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012336 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012337 __func__, __LINE__);
12338 hdd_perform_roam_set_key_complete(pAdapter);
12339 }
12340 }
12341
12342 pWextState->roamProfile.Keys.KeyLength[key_index] =
12343 (u8) params->key_len;
12344
12345 pWextState->roamProfile.Keys.defaultIndex = key_index;
12346
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012347 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012348 KeyMaterial[key_index][0], params->key,
12349 params->key_len);
12350
12351 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
12352
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012353 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012354 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12355 setKey.keyDirection);
12356
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012357 /* The supplicant may attempt to set the PTK once
12358 * pre-authentication is done. Save the key in the
12359 * UMAC and include it in the ADD BSS request
12360 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012361 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012362 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012363 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012364 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012365 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012366 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012367 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012368 return -EINVAL;
12369 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012370
12371 /* issue set key request to SME */
12372 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12373 pAdapter->sessionId, &setKey, &roamId);
12374
12375 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012376 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012377 pHddStaCtx->roam_info.roamingState =
12378 HDD_ROAM_STATE_NONE;
12379 return -EINVAL;
12380 }
12381
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012382 /* in case of IBSS as there was no information
12383 * available about WEP keys during IBSS join, group
12384 * key intialized with NULL key, so re-initialize
12385 * group key with correct value
12386 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012387 if ((eCSR_BSS_TYPE_START_IBSS ==
12388 pWextState->roamProfile.BSSType)
12389 &&
12390 !((IW_AUTH_KEY_MGMT_802_1X ==
12391 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
12392 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
12393 pHddStaCtx->conn_info.authType)
12394 )
12395 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
12396 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
12397 )
12398 ) {
12399 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012400 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012401
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012402 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012403 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12404 setKey.keyDirection);
12405
12406 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12407 pAdapter->sessionId, &setKey,
12408 &roamId);
12409
12410 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012411 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012412 pHddStaCtx->roam_info.roamingState =
12413 HDD_ROAM_STATE_NONE;
12414 return -EINVAL;
12415 }
12416 }
12417 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012418 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012419 return 0;
12420}
12421
12422static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12423 struct net_device *ndev,
12424 u8 key_index, bool pairwise,
12425 const u8 *mac_addr,
12426 struct key_params *params)
12427{
12428 int ret;
12429 cds_ssr_protect(__func__);
12430 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
12431 mac_addr, params);
12432 cds_ssr_unprotect(__func__);
12433
12434 return ret;
12435}
12436
12437/*
12438 * FUNCTION: __wlan_hdd_cfg80211_get_key
12439 * This function is used to get the key information
12440 */
12441static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12442 struct net_device *ndev,
12443 u8 key_index, bool pairwise,
12444 const u8 *mac_addr, void *cookie,
12445 void (*callback)(void *cookie,
12446 struct key_params *)
12447 )
12448{
12449 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12450 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12451 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
12452 struct key_params params;
12453
12454 ENTER();
12455
Anurag Chouhan6d760662016-02-20 16:05:43 +053012456 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012457 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458 return -EINVAL;
12459 }
12460
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012461 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012462 hdd_device_mode_to_string(pAdapter->device_mode),
12463 pAdapter->device_mode);
12464
12465 memset(&params, 0, sizeof(params));
12466
12467 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012468 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012469 return -EINVAL;
12470 }
12471
12472 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12473 case eCSR_ENCRYPT_TYPE_NONE:
12474 params.cipher = IW_AUTH_CIPHER_NONE;
12475 break;
12476
12477 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12478 case eCSR_ENCRYPT_TYPE_WEP40:
12479 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12480 break;
12481
12482 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12483 case eCSR_ENCRYPT_TYPE_WEP104:
12484 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12485 break;
12486
12487 case eCSR_ENCRYPT_TYPE_TKIP:
12488 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12489 break;
12490
12491 case eCSR_ENCRYPT_TYPE_AES:
12492 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12493 break;
12494
12495 default:
12496 params.cipher = IW_AUTH_CIPHER_NONE;
12497 break;
12498 }
12499
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012500 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012501 TRACE_CODE_HDD_CFG80211_GET_KEY,
12502 pAdapter->sessionId, params.cipher));
12503
12504 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12505 params.seq_len = 0;
12506 params.seq = NULL;
12507 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12508 callback(cookie, &params);
12509
12510 EXIT();
12511 return 0;
12512}
12513
12514static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12515 struct net_device *ndev,
12516 u8 key_index, bool pairwise,
12517 const u8 *mac_addr, void *cookie,
12518 void (*callback)(void *cookie,
12519 struct key_params *)
12520 )
12521{
12522 int ret;
12523
12524 cds_ssr_protect(__func__);
12525 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12526 mac_addr, cookie, callback);
12527 cds_ssr_unprotect(__func__);
12528
12529 return ret;
12530}
12531
12532/**
12533 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12534 * @wiphy: wiphy interface context
12535 * @ndev: pointer to net device
12536 * @key_index: Key index used in 802.11 frames
12537 * @unicast: true if it is unicast key
12538 * @multicast: true if it is multicast key
12539 *
12540 * This function is required for cfg80211_ops API.
12541 * It is used to delete the key information
12542 * Underlying hardware implementation does not have API to delete the
12543 * encryption key. It is automatically deleted when the peer is
12544 * removed. Hence this function currently does nothing.
12545 * Future implementation may interprete delete key operation to
12546 * replacing the key with a random junk value, effectively making it
12547 * useless.
12548 *
12549 * Return: status code, always 0.
12550 */
12551
12552static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12553 struct net_device *ndev,
12554 u8 key_index,
12555 bool pairwise, const u8 *mac_addr)
12556{
12557 EXIT();
12558 return 0;
12559}
12560
12561/**
12562 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12563 * @wiphy: Pointer to wiphy structure.
12564 * @dev: Pointer to net_device structure.
12565 * @key_index: key index
12566 * @pairwise: pairwise
12567 * @mac_addr: mac address
12568 *
12569 * This is the cfg80211 delete key handler function which invokes
12570 * the internal function @__wlan_hdd_cfg80211_del_key with
12571 * SSR protection.
12572 *
12573 * Return: 0 for success, error number on failure.
12574 */
12575static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12576 struct net_device *dev,
12577 u8 key_index,
12578 bool pairwise, const u8 *mac_addr)
12579{
12580 int ret;
12581
12582 cds_ssr_protect(__func__);
12583 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12584 pairwise, mac_addr);
12585 cds_ssr_unprotect(__func__);
12586
12587 return ret;
12588}
12589
12590/*
12591 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12592 * This function is used to set the default tx key index
12593 */
12594static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12595 struct net_device *ndev,
12596 u8 key_index,
12597 bool unicast, bool multicast)
12598{
12599 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12600 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12601 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12602 hdd_context_t *pHddCtx;
12603 int status;
12604
12605 ENTER();
12606
Anurag Chouhan6d760662016-02-20 16:05:43 +053012607 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012608 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012609 return -EINVAL;
12610 }
12611
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012612 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012613 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012614 return -EINVAL;
12615 }
12616
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012617 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012618 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12619 pAdapter->sessionId, key_index));
12620
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012621 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012622 hdd_device_mode_to_string(pAdapter->device_mode),
12623 pAdapter->device_mode, key_index);
12624
12625 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012626 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012627 return -EINVAL;
12628 }
12629
12630 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12631 status = wlan_hdd_validate_context(pHddCtx);
12632
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012633 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012634 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012635
Krunal Sonib4326f22016-03-10 13:05:51 -080012636 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12637 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012638 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12639 pHddStaCtx->conn_info.ucEncryptionType) &&
12640 (eCSR_ENCRYPT_TYPE_AES !=
12641 pHddStaCtx->conn_info.ucEncryptionType)) {
12642 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012643 * then update the default key index
12644 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012645
12646 tCsrRoamSetKey setKey;
12647 uint32_t roamId = 0xFF;
12648 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12649
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012650 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012651
12652 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012653 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012654 setKey.keyId = key_index;
12655 setKey.keyLength = Keys->KeyLength[key_index];
12656
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012657 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012658 &Keys->KeyMaterial[key_index][0],
12659 Keys->KeyLength[key_index]);
12660
12661 setKey.keyDirection = eSIR_TX_RX;
12662
Anurag Chouhanc5548422016-02-24 18:33:27 +053012663 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012664 &pHddStaCtx->conn_info.bssId);
12665
12666 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12667 pWextState->roamProfile.EncryptionType.
12668 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012669 /* In the case of dynamic wep
12670 * supplicant hardcodes DWEP type to
12671 * eCSR_ENCRYPT_TYPE_WEP104 even
12672 * though ap is configured for WEP-40
12673 * encryption. In this canse the key
12674 * length is 5 but the encryption type
12675 * is 104 hence checking the key
12676 * lenght(5) and encryption type(104)
12677 * and switching encryption type to 40
12678 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012679 pWextState->roamProfile.EncryptionType.
12680 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12681 pWextState->roamProfile.mcEncryptionType.
12682 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12683 }
12684
12685 setKey.encType =
12686 pWextState->roamProfile.EncryptionType.
12687 encryptionType[0];
12688
12689 /* Issue set key request */
12690 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12691 pAdapter->sessionId, &setKey,
12692 &roamId);
12693
12694 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012695 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012696 status);
12697 return -EINVAL;
12698 }
12699 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012700 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012701 /* In SoftAp mode setting key direction for default mode */
12702 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12703 pWextState->roamProfile.EncryptionType.encryptionType[0])
12704 && (eCSR_ENCRYPT_TYPE_AES !=
12705 pWextState->roamProfile.EncryptionType.
12706 encryptionType[0])) {
12707 /* Saving key direction for default key index to TX default */
12708 hdd_ap_ctx_t *pAPCtx =
12709 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12710 pAPCtx->wepKey[key_index].keyDirection =
12711 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012712 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012713 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012714 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012715 }
12716 }
12717
12718 EXIT();
12719 return status;
12720}
12721
12722static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12723 struct net_device *ndev,
12724 u8 key_index,
12725 bool unicast, bool multicast)
12726{
12727 int ret;
12728 cds_ssr_protect(__func__);
12729 ret =
12730 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12731 multicast);
12732 cds_ssr_unprotect(__func__);
12733
12734 return ret;
12735}
12736
Abhishek Singhc9941602016-08-09 16:06:22 +053012737/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012738 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12739 * interface that BSS might have been lost.
12740 * @pAdapter: adaptor
12741 * @bssid: bssid which might have been lost
12742 *
12743 * Return: bss which is unlinked from kernel cache
12744 */
12745struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12746 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012747{
12748 struct net_device *dev = pAdapter->dev;
12749 struct wireless_dev *wdev = dev->ieee80211_ptr;
12750 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012751 struct cfg80211_bss *bss = NULL;
12752
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012753 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012754 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012755 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012756 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012757 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012758 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012759 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760 cfg80211_unlink_bss(wiphy, bss);
12761 }
12762 return bss;
12763}
12764
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012765#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12766 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12767static struct cfg80211_bss *
12768wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12769 struct ieee80211_channel *chan,
12770 struct ieee80211_mgmt *mgmt,
12771 size_t frame_len,
12772 int rssi, gfp_t gfp,
12773 uint64_t boottime_ns)
12774{
12775 struct cfg80211_bss *bss_status = NULL;
12776 struct cfg80211_inform_bss data = {0};
12777
12778 data.chan = chan;
12779 data.boottime_ns = boottime_ns;
12780 data.signal = rssi;
12781 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12782 frame_len, gfp);
12783 return bss_status;
12784}
12785#else
12786static struct cfg80211_bss *
12787wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12788 struct ieee80211_channel *chan,
12789 struct ieee80211_mgmt *mgmt,
12790 size_t frame_len,
12791 int rssi, gfp_t gfp,
12792 uint64_t boottime_ns)
12793{
12794 struct cfg80211_bss *bss_status = NULL;
12795
12796 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12797 rssi, gfp);
12798 return bss_status;
12799}
12800#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012801
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012802/**
12803 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12804 * @pAdapter: Pointer to adapter
12805 * @bss_desc: Pointer to bss descriptor
12806 *
12807 * This function is used to inform the BSS details to nl80211 interface.
12808 *
12809 * Return: struct cfg80211_bss pointer
12810 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012811struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12812 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012813{
12814 /*
12815 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12816 * already exists in bss data base of cfg80211 for that particular BSS
12817 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12818 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12819 * As of now there is no possibility to get the mgmt(probe response)
12820 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12821 * and passing to cfg80211_inform_bss_frame.
12822 */
12823 struct net_device *dev = pAdapter->dev;
12824 struct wireless_dev *wdev = dev->ieee80211_ptr;
12825 struct wiphy *wiphy = wdev->wiphy;
12826 int chan_no = bss_desc->channelId;
12827#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12828 qcom_ie_age *qie_age = NULL;
12829 int ie_length =
12830 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12831#else
12832 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12833#endif
12834 const char *ie =
12835 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12836 unsigned int freq;
12837 struct ieee80211_channel *chan;
12838 struct ieee80211_mgmt *mgmt = NULL;
12839 struct cfg80211_bss *bss_status = NULL;
12840 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12841 int rssi = 0;
12842 hdd_context_t *pHddCtx;
12843 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012844 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012845 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012846
12847 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12848 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012849 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012850 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012851
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012852 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012853 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012854 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012855 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012856 return NULL;
12857 }
12858
12859 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12860
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012861 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012862 * Instead it wants a monotonic increasing value
12863 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012864 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012865 mgmt->u.probe_resp.timestamp =
12866 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012867
12868 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12869 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12870
12871#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12872 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12873 /* Assuming this is the last IE, copy at the end */
12874 ie_length -= sizeof(qcom_ie_age);
12875 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12876 qie_age->element_id = QCOM_VENDOR_IE_ID;
12877 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12878 qie_age->oui_1 = QCOM_OUI1;
12879 qie_age->oui_2 = QCOM_OUI2;
12880 qie_age->oui_3 = QCOM_OUI3;
12881 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012882 /*
12883 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12884 * all bss related timestamp is in units of ms. Due to this when scan
12885 * results are sent to lowi the scan age is high.To address this,
12886 * send age in units of 1/10 ms.
12887 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012888 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012889 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012890 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012891 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12892 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012893 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12894 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012895#endif
12896
12897 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12898 if (bss_desc->fProbeRsp) {
12899 mgmt->frame_control |=
12900 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12901 } else {
12902 mgmt->frame_control |=
12903 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12904 }
12905
12906 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012907 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908 freq =
12909 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012910 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012911 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012912 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012913 freq =
12914 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012915 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012916 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012917 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012918 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012919 return NULL;
12920 }
12921
12922 chan = __ieee80211_get_channel(wiphy, freq);
12923 /* When the band is changed on the fly using the GUI, three things are done
12924 * 1. scan abort
12925 * 2. flush scan results from cache
12926 * 3. update the band with the new band user specified (refer to the
12927 * hdd_set_band_helper function) as part of the scan abort, message will be
12928 * queued to PE and we proceed with flushing and changinh the band.
12929 * PE will stop the scanning further and report back the results what ever
12930 * it had till now by calling the call back function.
12931 * if the time between update band and scandone call back is sufficient
12932 * enough the band change reflects in SME, SME validates the channels
12933 * and discards the channels correponding to previous band and calls back
12934 * with zero bss results. but if the time between band update and scan done
12935 * callback is very small then band change will not reflect in SME and SME
12936 * reports to HDD all the channels correponding to previous band.this is due
12937 * to race condition.but those channels are invalid to the new band and so
12938 * this function __ieee80211_get_channel will return NULL.Each time we
12939 * report scan result with this pointer null warning kernel trace is printed.
12940 * if the scan results contain large number of APs continuosly kernel
12941 * warning trace is printed and it will lead to apps watch dog bark.
12942 * So drop the bss and continue to next bss.
12943 */
12944 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012945 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12946 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012947 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012948 return NULL;
12949 }
12950
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012951 /* Based on .ini configuration, raw rssi can be reported for bss.
12952 * Raw rssi is typically used for estimating power.
12953 */
12954
12955 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12956 bss_desc->rssi;
12957
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012958 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012959 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012960
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012961 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012962 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012963 (int)(rssi / 100),
12964 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012965
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012966 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12967 frame_len, rssi,
12968 GFP_KERNEL,
12969 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012970 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012971 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012972 return bss_status;
12973}
12974
12975/**
12976 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12977 * @pAdapter: Pointer to adapter
12978 * @pRoamInfo: Pointer to roam info
12979 *
12980 * This function is used to update the BSS data base of CFG8011
12981 *
12982 * Return: struct cfg80211_bss pointer
12983 */
12984struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12985 tCsrRoamInfo *pRoamInfo)
12986{
12987 tCsrRoamConnectedProfile roamProfile;
12988 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12989 struct cfg80211_bss *bss = NULL;
12990
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012991 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12992 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12993
12994 if (NULL != roamProfile.pBssDesc) {
12995 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12996 roamProfile.pBssDesc);
12997
12998 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012999 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013000
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080013001 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013002 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013003 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013004 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013005 return bss;
13006}
13007/**
13008 * wlan_hdd_cfg80211_update_bss() - update bss
13009 * @wiphy: Pointer to wiphy
13010 * @pAdapter: Pointer to adapter
13011 * @scan_time: scan request timestamp
13012 *
13013 * Return: zero if success, non-zero otherwise
13014 */
13015int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
13016 hdd_adapter_t *pAdapter,
13017 uint32_t scan_time)
13018{
13019 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13020 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013021 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013022 tScanResultHandle pResult;
13023 struct cfg80211_bss *bss_status = NULL;
13024 hdd_context_t *pHddCtx;
13025 int ret;
13026
13027 ENTER();
13028
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013029 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13030 hdd_err("invalid session id: %d", pAdapter->sessionId);
13031 return -EINVAL;
13032 }
13033
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013034 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013035 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
13036 NO_SESSION, pAdapter->sessionId));
13037
13038 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13039 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013040 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013041 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013042
13043 /* start getting scan results and populate cgf80211 BSS database */
13044 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
13045
13046 /* no scan results */
13047 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013048 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053013049 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013050 }
13051
13052 pScanResult = sme_scan_result_get_first(hHal, pResult);
13053
13054 while (pScanResult) {
13055 /*
13056 * - cfg80211_inform_bss() is not updating ie field of bss
13057 * entry if entry already exists in bss data base of cfg80211
13058 * for that particular BSS ID. Using cfg80211_inform_bss_frame
13059 * to update thebss entry instead of cfg80211_inform_bss,
13060 * But this call expects mgmt packet as input. As of now
13061 * there is no possibility to get the mgmt(probe response)
13062 * frame from PE, converting bss_desc to
13063 * ieee80211_mgmt(probe response) and passing to c
13064 * fg80211_inform_bss_frame.
13065 * - Update BSS only if beacon timestamp is later than
13066 * scan request timestamp.
13067 */
13068 if ((scan_time == 0) ||
13069 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053013070 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013071 bss_status =
13072 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
13073 &pScanResult->BssDescriptor);
13074
13075 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013076 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013077 } else {
13078 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013079 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013080 bss_status);
13081 }
13082 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013083 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
13085 }
13086 pScanResult = sme_scan_result_get_next(hHal, pResult);
13087 }
13088
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070013089 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 /*
13091 * For SAP mode, scan is invoked by hostapd during SAP start
13092 * if hostapd is restarted, we need to flush previous scan
13093 * result so that it will reflect environment change
13094 */
Krunal Sonib4326f22016-03-10 13:05:51 -080013095 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013096#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
13097 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
13098#endif
13099 )
13100 sme_scan_flush_result(hHal);
13101
13102 EXIT();
13103 return 0;
13104}
13105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013106/**
13107 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
13108 * @pAdapter: Pointer to adapter
13109 * @pRoamInfo: Pointer to roam info
13110 * @index: Index
13111 * @preauth: Preauth flag
13112 *
13113 * This function is used to notify the supplicant of a new PMKSA candidate.
13114 *
13115 * Return: 0 for success, non-zero for failure
13116 */
13117int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
13118 tCsrRoamInfo *pRoamInfo,
13119 int index, bool preauth)
13120{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013121 struct net_device *dev = pAdapter->dev;
13122 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
13123
13124 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013125 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013126
13127 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013128 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013129 return -EINVAL;
13130 }
13131
13132 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013133 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013134 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
13135 cfg80211_pmksa_candidate_notify(dev, index,
13136 pRoamInfo->bssid.bytes,
13137 preauth, GFP_KERNEL);
13138 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013139 return 0;
13140}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013141
13142#ifdef FEATURE_WLAN_LFR_METRICS
13143/**
13144 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
13145 * @pAdapter: Pointer to adapter
13146 * @pRoamInfo: Pointer to roam info
13147 *
13148 * 802.11r/LFR metrics reporting function to report preauth initiation
13149 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013150 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013151 */
13152#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013153QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013154 tCsrRoamInfo *pRoamInfo)
13155{
13156 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13157 union iwreq_data wrqu;
13158
13159 ENTER();
13160
13161 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013162 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013163 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013164 }
13165
13166 /* create the event */
13167 memset(&wrqu, 0, sizeof(wrqu));
13168 memset(metrics_notification, 0, sizeof(metrics_notification));
13169
13170 wrqu.data.pointer = metrics_notification;
13171 wrqu.data.length = scnprintf(metrics_notification,
13172 sizeof(metrics_notification),
13173 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013174 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013175
13176 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13177 metrics_notification);
13178
13179 EXIT();
13180
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013181 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013182}
13183
13184/**
13185 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13186 * @pAdapter: Pointer to adapter
13187 * @pRoamInfo: Pointer to roam info
13188 * @preauth_status: Preauth status
13189 *
13190 * 802.11r/LFR metrics reporting function to report handover initiation
13191 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013192 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013193 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013194QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013195wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
13196 tCsrRoamInfo *pRoamInfo,
13197 bool preauth_status)
13198{
13199 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13200 union iwreq_data wrqu;
13201
13202 ENTER();
13203
13204 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013205 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013206 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013207 }
13208
13209 /* create the event */
13210 memset(&wrqu, 0, sizeof(wrqu));
13211 memset(metrics_notification, 0, sizeof(metrics_notification));
13212
13213 scnprintf(metrics_notification, sizeof(metrics_notification),
13214 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013215 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013216
13217 if (1 == preauth_status)
13218 strlcat(metrics_notification, " true",
13219 sizeof(metrics_notification));
13220 else
13221 strlcat(metrics_notification, " false",
13222 sizeof(metrics_notification));
13223
13224 wrqu.data.pointer = metrics_notification;
13225 wrqu.data.length = strlen(metrics_notification);
13226
13227 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13228 metrics_notification);
13229
13230 EXIT();
13231
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013232 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233}
13234
13235/**
13236 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13237 * @pAdapter: Pointer to adapter
13238 * @pRoamInfo: Pointer to roam info
13239 *
13240 * 802.11r/LFR metrics reporting function to report handover initiation
13241 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013242 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013243 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013244QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013245 tCsrRoamInfo *pRoamInfo)
13246{
13247 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13248 union iwreq_data wrqu;
13249
13250 ENTER();
13251
13252 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013253 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013254 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013255 }
13256
13257 /* create the event */
13258 memset(&wrqu, 0, sizeof(wrqu));
13259 memset(metrics_notification, 0, sizeof(metrics_notification));
13260
13261 wrqu.data.pointer = metrics_notification;
13262 wrqu.data.length = scnprintf(metrics_notification,
13263 sizeof(metrics_notification),
13264 "QCOM: LFR_PREAUTH_HANDOVER "
13265 MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013266 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013267
13268 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13269 metrics_notification);
13270
13271 EXIT();
13272
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013273 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274}
13275#endif
13276
13277/**
13278 * hdd_select_cbmode() - select channel bonding mode
13279 * @pAdapter: Pointer to adapter
13280 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013281 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282 *
13283 * Return: none
13284 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013285void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080013286 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013287{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013288 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013289 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013290 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013291 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013292
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013293 /*
13294 * CDS api expects secondary channel for calculating
13295 * the channel params
13296 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013297 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013298 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013299 if (operationChannel >= 1 && operationChannel <= 5)
13300 sec_ch = operationChannel + 4;
13301 else if (operationChannel >= 6 && operationChannel <= 13)
13302 sec_ch = operationChannel - 4;
13303 }
13304
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013305 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013306 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
13307 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013308
13309 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070013310 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013311 uint8_t iniDot11Mode =
13312 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
13313
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013314 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013315 switch (iniDot11Mode) {
13316 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080013317 case eHDD_DOT11_MODE_11ax:
13318 case eHDD_DOT11_MODE_11ax_ONLY:
13319 if (sme_is_feature_supported_by_fw(DOT11AX))
13320 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
13321 else if (sme_is_feature_supported_by_fw(DOT11AC))
13322 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13323 else
13324 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13325 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013326 case eHDD_DOT11_MODE_11ac:
13327 case eHDD_DOT11_MODE_11ac_ONLY:
13328 if (sme_is_feature_supported_by_fw(DOT11AC))
13329 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13330 else
13331 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13332 break;
13333 case eHDD_DOT11_MODE_11n:
13334 case eHDD_DOT11_MODE_11n_ONLY:
13335 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13336 break;
13337 default:
13338 hdd_dot11_mode = iniDot11Mode;
13339 break;
13340 }
13341 ch_info->channel_width = ch_params->ch_width;
13342 ch_info->phy_mode =
13343 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013344 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013345 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013346 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013347 ch_info->channel_width, ch_info->phy_mode,
13348 ch_info->channel);
13349 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013350}
13351
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013352/**
13353 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
13354 * @adapter: STA adapter
13355 * @roam_profile: STA roam profile
13356 *
13357 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
13358 *
13359 * Return: false if sta-sap conc is not allowed, else return true
13360 */
13361static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
13362 tCsrRoamProfile *roam_profile)
13363{
13364 hdd_context_t *hdd_ctx;
13365 hdd_adapter_t *ap_adapter;
13366 hdd_ap_ctx_t *hdd_ap_ctx;
13367 hdd_hostapd_state_t *hostapd_state;
13368 uint8_t channel = 0;
13369 QDF_STATUS status;
13370
13371 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13372 if (!hdd_ctx) {
13373 hdd_err("HDD context is NULL");
13374 return true;
13375 }
13376
13377 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
13378 /* probably no sap running, no handling required */
13379 if (ap_adapter == NULL)
13380 return true;
13381
13382 /*
13383 * sap is not in started state, so it is fine to go ahead with sta.
13384 * if sap is currently doing CAC then don't allow sta to go further.
13385 */
13386 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
13387 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
13388 return true;
13389
13390 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
13391 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
13392 return false;
13393 }
13394
13395 /*
13396 * log and return error, if we allow STA to go through, we don't
13397 * know what is going to happen better stop sta connection
13398 */
13399 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
13400 if (NULL == hdd_ap_ctx) {
13401 hdd_err("AP context not found");
13402 return false;
13403 }
13404
13405 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013406 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
13407 hdd_ap_ctx->operatingChannel)) {
13408 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013409 return true;
13410 }
13411 /*
13412 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053013413 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013414 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013415 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013416 roam_profile, &channel);
13417
Nitesh Shah59774522016-09-16 15:14:21 +053013418 /*
13419 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
13420 * channels for roaming case.
13421 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013422 if (WLAN_REG_IS_24GHZ_CH(channel)) {
13423 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053013424 return true;
13425 }
13426
13427 /*
13428 * If channel is 0 or DFS then better to call pcl and find out the
13429 * best channel. If channel is non-dfs 5 GHz then better move SAP
13430 * to STA's channel to make scc, so we have room for 3port MCC
13431 * scenario.
13432 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013433 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013434 channel = policy_mgr_get_nondfs_preferred_channel(
13435 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013436
13437 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
13438 qdf_event_reset(&hostapd_state->qdf_event);
13439 status = wlansap_set_channel_change_with_csa(
13440 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
13441 hdd_ap_ctx->sapConfig.ch_width_orig);
13442
13443 if (QDF_STATUS_SUCCESS != status) {
13444 hdd_err("Set channel with CSA IE failed, can't allow STA");
13445 return false;
13446 }
13447
13448 /*
13449 * wait here for SAP to finish the channel switch. When channel
13450 * switch happens, SAP sends few beacons with CSA_IE. After
13451 * successfully Transmission of those beacons, it will move its
13452 * state from started to disconnected and move to new channel.
13453 * once it moves to new channel, sap again moves its state
13454 * machine from disconnected to started and set this event.
13455 * wait for 10 secs to finish this.
13456 */
13457 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
13458 if (!QDF_IS_STATUS_SUCCESS(status)) {
13459 hdd_err("wait for qdf_event failed, STA not allowed!!");
13460 return false;
13461 }
13462
13463 return true;
13464}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013465
Abhishek Singhcfb44482017-03-10 12:42:37 +053013466#ifdef WLAN_FEATURE_11W
13467/**
13468 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13469 * @roam_profile: pointer to roam profile
13470 *
13471 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13472 * or pmf=2 is an explicit configuration in the supplicant
13473 * configuration, drop the connection request.
13474 *
13475 * Return: 0 if check result is valid, otherwise return error code
13476 */
13477static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13478{
13479 if (roam_profile->MFPEnabled &&
13480 !(roam_profile->MFPRequired ||
13481 roam_profile->MFPCapable)) {
13482 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13483 roam_profile->MFPEnabled,
13484 roam_profile->MFPRequired,
13485 roam_profile->MFPCapable);
13486 return -EINVAL;
13487 }
13488 return 0;
13489}
13490#else
13491static inline
13492int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13493{
13494 return 0;
13495}
13496#endif
13497
Krunal Soni31949422016-07-29 17:17:53 -070013498/**
13499 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013500 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013501 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013502 * @ssid_len: Length of ssid
13503 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013504 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013505 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013506 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013507 *
13508 * This function is used to start the association process
13509 *
13510 * Return: 0 for success, non-zero for failure
13511 */
Krunal Soni31949422016-07-29 17:17:53 -070013512static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013514 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013515 u8 operatingChannel,
13516 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013517{
13518 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013519 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013520 hdd_wext_state_t *pWextState;
13521 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013522 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013523 uint32_t roamId;
13524 tCsrRoamProfile *pRoamProfile;
13525 eCsrAuthType RSNAuthType;
13526 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013527 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013528
13529 ENTER();
13530
13531 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13532 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013533 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013534
13535 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013536 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013537 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013538
13539 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013540 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013541 status = -EINVAL;
13542 goto ret_status;
13543 }
13544
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013545 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013546 hdd_err("Connection refused: conn in progress");
13547 status = -EINVAL;
13548 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013549 }
13550
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013551 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013552 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13553
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013554 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013555 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13556 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013557
13558 if (pRoamProfile) {
13559 hdd_station_ctx_t *pHddStaCtx;
13560 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13561
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013562 /* Restart the opportunistic timer
13563 *
13564 * If hw_mode_change_in_progress is true, then wait
13565 * till firmware sends the callback for hw_mode change.
13566 *
13567 * Else set connect_in_progress as true and proceed.
13568 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013569 policy_mgr_restart_opportunistic_timer(
13570 pHddCtx->hdd_psoc, false);
13571 if (policy_mgr_is_hw_mode_change_in_progress(
13572 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013573 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013574 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013575 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013576 hdd_err("qdf wait for event failed!!");
13577 status = -EINVAL;
13578 goto ret_status;
13579 }
13580 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013581 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013582
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013583 if (HDD_WMM_USER_MODE_NO_QOS ==
13584 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13585 /*QoS not enabled in cfg file */
13586 pRoamProfile->uapsd_mask = 0;
13587 } else {
13588 /*QoS enabled, update uapsd mask from cfg file */
13589 pRoamProfile->uapsd_mask =
13590 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13591 }
13592
13593 pRoamProfile->SSIDs.numOfSSIDs = 1;
13594 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013595 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013596 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013597 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013598 ssid, ssid_len);
13599
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013600 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013601 /* cleanup bssid hint */
13602 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13603 QDF_MAC_ADDR_SIZE);
13604 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13605 QDF_MAC_ADDR_SIZE);
13606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013607 if (bssid) {
13608 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013609 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013610 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013611 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013612 /*
13613 * Save BSSID in seperate variable as
13614 * pRoamProfile's BSSID is getting zeroed out in the
13615 * association process. In case of join failure
13616 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013618 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013619 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013620 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013621 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013622 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13623 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013624 /*
13625 * Save BSSID in a separate variable as
13626 * pRoamProfile's BSSID is getting zeroed out in the
13627 * association process. In case of join failure
13628 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013629 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013630 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013631 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013632 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013633 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013634 }
13635
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013636 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013637 pRoamProfile->SSIDs.SSIDList->SSID.length,
13638 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13639 operatingChannel);
13640
13641 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13642 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013644 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13645 }
13646#ifdef FEATURE_WLAN_WAPI
13647 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013648 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013649 switch (pAdapter->wapi_info.wapiAuthMode) {
13650 case WAPI_AUTH_MODE_PSK:
13651 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013652 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013653 pAdapter->wapi_info.wapiAuthMode);
13654 pRoamProfile->AuthType.authType[0] =
13655 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13656 break;
13657 }
13658 case WAPI_AUTH_MODE_CERT:
13659 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013660 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013661 pAdapter->wapi_info.wapiAuthMode);
13662 pRoamProfile->AuthType.authType[0] =
13663 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13664 break;
13665 }
13666 } /* End of switch */
13667 if (pAdapter->wapi_info.wapiAuthMode ==
13668 WAPI_AUTH_MODE_PSK
13669 || pAdapter->wapi_info.wapiAuthMode ==
13670 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013671 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013672 pRoamProfile->AuthType.numEntries = 1;
13673 pRoamProfile->EncryptionType.numEntries = 1;
13674 pRoamProfile->EncryptionType.encryptionType[0] =
13675 eCSR_ENCRYPT_TYPE_WPI;
13676 pRoamProfile->mcEncryptionType.numEntries = 1;
13677 pRoamProfile->mcEncryptionType.
13678 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13679 }
13680 }
Krunal Soni31949422016-07-29 17:17:53 -070013681#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013682 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013683 pRoamProfile->csrPersona = pAdapter->device_mode;
13684
13685 if (operatingChannel) {
13686 pRoamProfile->ChannelInfo.ChannelList =
13687 &operatingChannel;
13688 pRoamProfile->ChannelInfo.numOfChannels = 1;
13689 } else {
13690 pRoamProfile->ChannelInfo.ChannelList = NULL;
13691 pRoamProfile->ChannelInfo.numOfChannels = 0;
13692 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013693 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694 && operatingChannel) {
13695 /*
13696 * Need to post the IBSS power save parameters
13697 * to WMA. WMA will configure this parameters
13698 * to firmware if power save is enabled by the
13699 * firmware.
13700 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013701 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013702
Abhishek Singh471652b2017-04-14 12:28:32 +053013703 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013704 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013705 status = -EINVAL;
13706 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013707 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013708 pRoamProfile->ch_params.ch_width =
13709 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013710 /*
13711 * In IBSS mode while operating in 2.4 GHz,
13712 * the device supports only 20 MHz.
13713 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013714 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013715 pRoamProfile->ch_params.ch_width =
13716 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013717 hdd_select_cbmode(pAdapter, operatingChannel,
13718 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013719 }
13720
Abhishek Singhcfb44482017-03-10 12:42:37 +053013721 if (wlan_hdd_cfg80211_check_pmf_valid(
13722 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013723 status = -EINVAL;
13724 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013725 }
13726
Krunal Soni31949422016-07-29 17:17:53 -070013727 /*
13728 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013729 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013730 * enhancements, the supplicant is not issuing the scan command
13731 * now. So the unicast frames which are sent from the host are
13732 * not having the additional IEs. If it is P2P CLIENT and there
13733 * is no additional IE present in roamProfile, then use the
13734 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013735 */
13736
Krunal Sonib4326f22016-03-10 13:05:51 -080013737 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013738 (!pRoamProfile->pAddIEScan)) {
13739 pRoamProfile->pAddIEScan =
13740 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13741 pRoamProfile->nAddIEScanLength =
13742 pAdapter->scan_info.scanAddIE.length;
13743 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013745 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13746 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013747 pRoamProfile))) {
13748 hdd_err("sap-sta conc will fail, can't allow sta");
13749 hdd_conn_set_connection_state(pAdapter,
13750 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013751 status = -ENOMEM;
13752 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013753 }
13754
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013755 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013756 if (!sme_config) {
13757 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013758 hdd_conn_set_connection_state(pAdapter,
13759 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013760 status = -ENOMEM;
13761 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013762 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013763 sme_get_config_param(pHddCtx->hHal, sme_config);
13764 /* These values are not sessionized. So, any change in these SME
13765 * configs on an older or parallel interface will affect the
13766 * cb mode. So, restoring the default INI params before starting
13767 * interfaces such as sta, cli etc.,
13768 */
13769 sme_config->csrConfig.channelBondingMode5GHz =
13770 pHddCtx->config->nChannelBondingMode5GHz;
13771 sme_config->csrConfig.channelBondingMode24GHz =
13772 pHddCtx->config->nChannelBondingMode24GHz;
13773 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013774 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013775 /*
13776 * Change conn_state to connecting before sme_roam_connect(),
13777 * because sme_roam_connect() has a direct path to call
13778 * hdd_sme_roam_callback(), which will change the conn_state
13779 * If direct path, conn_state will be accordingly changed to
13780 * NotConnected or Associated by either
13781 * hdd_association_completion_handler() or
13782 * hdd_dis_connect_handler() in sme_RoamCallback()if
13783 * sme_RomConnect is to be queued,
13784 * Connecting state will remain until it is completed.
13785 *
13786 * If connection state is not changed, connection state will
13787 * remain in eConnectionState_NotConnected state.
13788 * In hdd_association_completion_handler, "hddDisconInProgress"
13789 * is set to true if conn state is
13790 * eConnectionState_NotConnected.
13791 * If "hddDisconInProgress" is set to true then cfg80211 layer
13792 * is not informed of connect result indication which
13793 * is an issue.
13794 */
13795 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013796 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013797 hdd_conn_set_connection_state(pAdapter,
13798 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013799
Komal Seelama89be8d2016-09-29 11:09:26 +053013800 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13801 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013802 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013803 pAdapter->sessionId, pRoamProfile,
13804 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013805 if (QDF_IS_STATUS_ERROR(qdf_status))
13806 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013807
Rajeev Kumard31e1542017-01-13 14:37:42 -080013808 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013809 (QDF_STA_MODE == pAdapter->device_mode ||
13810 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013811 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013812 "qdf_status %d. -> NotConnected",
13813 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013814 /* change back to NotAssociated */
13815 hdd_conn_set_connection_state(pAdapter,
13816 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013817 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13818 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013819 }
13820
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013821 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013822 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013823
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013824 pRoamProfile->ChannelInfo.ChannelList = NULL;
13825 pRoamProfile->ChannelInfo.numOfChannels = 0;
13826
Nitesh Shah044fd672016-10-13 18:53:25 +053013827 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013828 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13829 && !policy_mgr_is_hw_dbs_2x2_capable(
13830 pHddCtx->hdd_psoc)) {
13831 policy_mgr_get_channel_from_scan_result(
13832 pHddCtx->hdd_psoc,
13833 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013834 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013835 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013836 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13837 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013838 }
13839
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013841 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013842 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013843 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013844 goto ret_status;
13845
13846conn_failure:
13847 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013848 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013849
13850ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 EXIT();
13852 return status;
13853}
13854
13855/**
13856 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13857 * @pAdapter: Pointer to adapter
13858 * @auth_type: Auth type
13859 *
13860 * This function is used to set the authentication type (OPEN/SHARED).
13861 *
13862 * Return: 0 for success, non-zero for failure
13863 */
13864static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13865 enum nl80211_auth_type auth_type)
13866{
13867 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13868 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13869
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013870 /*set authentication type */
13871 switch (auth_type) {
13872 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013873 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013874 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13875 break;
13876
13877 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013878 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013879 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13881 break;
13882
13883 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013884 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013885 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13886 break;
13887#ifdef FEATURE_WLAN_ESE
13888 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013889 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013890 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13891 break;
13892#endif
13893
13894 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013895 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013896 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13897 return -EINVAL;
13898 }
13899
13900 pWextState->roamProfile.AuthType.authType[0] =
13901 pHddStaCtx->conn_info.authType;
13902 return 0;
13903}
13904
13905/**
13906 * wlan_hdd_set_akm_suite() - set key management type
13907 * @pAdapter: Pointer to adapter
13908 * @key_mgmt: Key management type
13909 *
13910 * This function is used to set the key mgmt type(PSK/8021x).
13911 *
13912 * Return: 0 for success, non-zero for failure
13913 */
13914static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13915{
13916 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13917
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013918#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013919#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013920#endif
13921#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013922#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013923#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013924 /*set key mgmt type */
13925 switch (key_mgmt) {
13926 case WLAN_AKM_SUITE_PSK:
13927 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013928 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013929 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013930 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13931 break;
13932
13933 case WLAN_AKM_SUITE_8021X_SHA256:
13934 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013935 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013936 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13938 break;
13939#ifdef FEATURE_WLAN_ESE
13940#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13941#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13942 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013943 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013944 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13945 break;
13946#endif
13947#ifndef WLAN_AKM_SUITE_OSEN
13948#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13949#endif
13950 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013951 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013952 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13953 break;
13954
13955 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013956 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013957 return -EINVAL;
13958
13959 }
13960 return 0;
13961}
13962
13963/**
13964 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13965 * @pAdapter: Pointer to adapter
13966 * @cipher: Cipher type
13967 * @ucast: Unicast flag
13968 *
13969 * This function is used to set the encryption type
13970 * (NONE/WEP40/WEP104/TKIP/CCMP).
13971 *
13972 * Return: 0 for success, non-zero for failure
13973 */
13974static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13975 u32 cipher, bool ucast)
13976{
13977 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13978 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13979 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13980
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013981 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013982 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013983 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13984 } else {
13985
13986 /*set encryption method */
13987 switch (cipher) {
13988 case IW_AUTH_CIPHER_NONE:
13989 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13990 break;
13991
13992 case WLAN_CIPHER_SUITE_WEP40:
13993 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13994 break;
13995
13996 case WLAN_CIPHER_SUITE_WEP104:
13997 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13998 break;
13999
14000 case WLAN_CIPHER_SUITE_TKIP:
14001 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
14002 break;
14003
14004 case WLAN_CIPHER_SUITE_CCMP:
14005 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14006 break;
14007#ifdef FEATURE_WLAN_WAPI
14008 case WLAN_CIPHER_SUITE_SMS4:
14009 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
14010 break;
14011#endif
14012
14013#ifdef FEATURE_WLAN_ESE
14014 case WLAN_CIPHER_SUITE_KRK:
14015 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
14016 break;
14017#ifdef WLAN_FEATURE_ROAM_OFFLOAD
14018 case WLAN_CIPHER_SUITE_BTK:
14019 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
14020 break;
14021#endif
14022#endif
14023 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014024 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014025 return -EOPNOTSUPP;
14026 }
14027 }
14028
14029 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014030 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014031 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14032 pWextState->roamProfile.EncryptionType.numEntries = 1;
14033 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14034 encryptionType;
14035 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014036 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014037 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
14038 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
14039 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
14040 encryptionType;
14041 }
14042
14043 return 0;
14044}
14045
14046/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014047 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
14048 * @wext_state: Pointer to wext state
14049 * @gen_ie: Pointer to IE data
14050 * @len: length of IE data
14051 *
14052 * Return: 0 for success, non-zero for failure
14053 */
14054static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
14055 const uint8_t *gen_ie, uint16_t len)
14056{
14057 uint16_t cur_add_ie_len =
14058 wext_state->assocAddIE.length;
14059
14060 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14061 (wext_state->assocAddIE.length + len)) {
14062 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
14063 QDF_ASSERT(0);
14064 return -ENOMEM;
14065 }
14066 memcpy(wext_state->assocAddIE.addIEdata +
14067 cur_add_ie_len, gen_ie, len);
14068 wext_state->assocAddIE.length += len;
14069
14070 wext_state->roamProfile.pAddIEAssoc =
14071 wext_state->assocAddIE.addIEdata;
14072 wext_state->roamProfile.nAddIEAssocLength =
14073 wext_state->assocAddIE.length;
14074 return 0;
14075}
14076
14077/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014078 * wlan_hdd_cfg80211_set_ie() - set IEs
14079 * @pAdapter: Pointer to adapter
14080 * @ie: Pointer ot ie
14081 * @ie: IE length
14082 *
14083 * Return: 0 for success, non-zero for failure
14084 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014085static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014086 size_t ie_len)
14087{
14088 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14089 const uint8_t *genie = ie;
14090 uint16_t remLen = ie_len;
14091#ifdef FEATURE_WLAN_WAPI
14092 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
14093 u16 *tmp;
14094 uint16_t akmsuiteCount;
14095 int *akmlist;
14096#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014097 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014098
14099 /* clear previous assocAddIE */
14100 pWextState->assocAddIE.length = 0;
14101 pWextState->roamProfile.bWPSAssociation = false;
14102 pWextState->roamProfile.bOSENAssociation = false;
14103
14104 while (remLen >= 2) {
14105 uint16_t eLen = 0;
14106 uint8_t elementId;
14107 elementId = *genie++;
14108 eLen = *genie++;
14109 remLen -= 2;
14110
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014111 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014112
14113 switch (elementId) {
14114 case DOT11F_EID_WPA:
14115 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 -070014116 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014117 return -EINVAL;
14118 } else if (0 ==
14119 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
14120 uint16_t curAddIELen =
14121 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014122 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014123
14124 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14125 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014126 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014127 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014128 return -ENOMEM;
14129 }
14130 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
14131 memcpy(pWextState->assocAddIE.addIEdata +
14132 curAddIELen, genie - 2, eLen + 2);
14133 pWextState->assocAddIE.length += eLen + 2;
14134
14135 pWextState->roamProfile.bWPSAssociation = true;
14136 pWextState->roamProfile.pAddIEAssoc =
14137 pWextState->assocAddIE.addIEdata;
14138 pWextState->roamProfile.nAddIEAssocLength =
14139 pWextState->assocAddIE.length;
14140 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014141 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 memset(pWextState->WPARSNIE, 0,
14143 MAX_WPA_RSN_IE_LEN);
14144 memcpy(pWextState->WPARSNIE, genie - 2,
14145 (eLen + 2));
14146 pWextState->roamProfile.pWPAReqIE =
14147 pWextState->WPARSNIE;
14148 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
14149 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
14150 P2P_OUI_TYPE_SIZE))) {
14151 uint16_t curAddIELen =
14152 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014153 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014154
14155 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14156 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014157 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014158 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014159 return -ENOMEM;
14160 }
14161 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
14162 memcpy(pWextState->assocAddIE.addIEdata +
14163 curAddIELen, genie - 2, eLen + 2);
14164 pWextState->assocAddIE.length += eLen + 2;
14165
14166 pWextState->roamProfile.pAddIEAssoc =
14167 pWextState->assocAddIE.addIEdata;
14168 pWextState->roamProfile.nAddIEAssocLength =
14169 pWextState->assocAddIE.length;
14170 }
14171#ifdef WLAN_FEATURE_WFD
14172 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
14173 WFD_OUI_TYPE_SIZE)) &&
14174 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080014175 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014176 pAdapter->device_mode)) {
14177 uint16_t curAddIELen =
14178 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014179 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014180
14181 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14182 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014183 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014184 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014185 return -ENOMEM;
14186 }
14187 /* WFD IE is saved to Additional IE ; it should
14188 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014189 * WFD IE
14190 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014191 memcpy(pWextState->assocAddIE.addIEdata +
14192 curAddIELen, genie - 2, eLen + 2);
14193 pWextState->assocAddIE.length += eLen + 2;
14194
14195 pWextState->roamProfile.pAddIEAssoc =
14196 pWextState->assocAddIE.addIEdata;
14197 pWextState->roamProfile.nAddIEAssocLength =
14198 pWextState->assocAddIE.length;
14199 }
14200#endif
14201 /* Appending HS 2.0 Indication Element in Assiciation Request */
14202 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
14203 HS20_OUI_TYPE_SIZE))) {
14204 uint16_t curAddIELen =
14205 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014206 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014207
14208 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14209 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014210 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014211 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014212 return -ENOMEM;
14213 }
14214 memcpy(pWextState->assocAddIE.addIEdata +
14215 curAddIELen, genie - 2, eLen + 2);
14216 pWextState->assocAddIE.length += eLen + 2;
14217
14218 pWextState->roamProfile.pAddIEAssoc =
14219 pWextState->assocAddIE.addIEdata;
14220 pWextState->roamProfile.nAddIEAssocLength =
14221 pWextState->assocAddIE.length;
14222 }
14223 /* Appending OSEN Information Element in Assiciation Request */
14224 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
14225 OSEN_OUI_TYPE_SIZE))) {
14226 uint16_t curAddIELen =
14227 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014228 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014229
14230 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14231 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014232 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014233 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014234 return -ENOMEM;
14235 }
14236 memcpy(pWextState->assocAddIE.addIEdata +
14237 curAddIELen, genie - 2, eLen + 2);
14238 pWextState->assocAddIE.length += eLen + 2;
14239
14240 pWextState->roamProfile.bOSENAssociation = true;
14241 pWextState->roamProfile.pAddIEAssoc =
14242 pWextState->assocAddIE.addIEdata;
14243 pWextState->roamProfile.nAddIEAssocLength =
14244 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014245 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
14246 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014247 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014248 status = wlan_hdd_add_assoc_ie(pWextState,
14249 genie - 2, eLen + 2);
14250 if (status)
14251 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014252 } else {
14253 uint16_t add_ie_len =
14254 pWextState->assocAddIE.length;
14255
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014256 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014257
14258 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14259 (pWextState->assocAddIE.length + eLen)) {
14260 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014261 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014262 return -ENOMEM;
14263 }
14264
14265 memcpy(pWextState->assocAddIE.addIEdata +
14266 add_ie_len, genie - 2, eLen + 2);
14267 pWextState->assocAddIE.length += eLen + 2;
14268
14269 pWextState->roamProfile.pAddIEAssoc =
14270 pWextState->assocAddIE.addIEdata;
14271 pWextState->roamProfile.nAddIEAssocLength =
14272 pWextState->assocAddIE.length;
14273 }
14274 break;
14275 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014276 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014277 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
14278 memcpy(pWextState->WPARSNIE, genie - 2,
14279 (eLen + 2));
14280 pWextState->roamProfile.pRSNReqIE =
14281 pWextState->WPARSNIE;
14282 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
14283 break;
14284 /*
14285 * Appending Extended Capabilities with Interworking bit set
14286 * in Assoc Req.
14287 *
14288 * In assoc req this EXT Cap will only be taken into account if
14289 * interworkingService bit is set to 1. Currently
14290 * driver is only interested in interworkingService capability
14291 * from supplicant. If in future any other EXT Cap info is
14292 * required from supplicat, it needs to be handled while
14293 * sending Assoc Req in LIM.
14294 */
14295 case DOT11F_EID_EXTCAP:
14296 {
14297 uint16_t curAddIELen =
14298 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014299 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014300
14301 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14302 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014303 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014304 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014305 return -ENOMEM;
14306 }
14307 memcpy(pWextState->assocAddIE.addIEdata +
14308 curAddIELen, genie - 2, eLen + 2);
14309 pWextState->assocAddIE.length += eLen + 2;
14310
14311 pWextState->roamProfile.pAddIEAssoc =
14312 pWextState->assocAddIE.addIEdata;
14313 pWextState->roamProfile.nAddIEAssocLength =
14314 pWextState->assocAddIE.length;
14315 break;
14316 }
14317#ifdef FEATURE_WLAN_WAPI
14318 case WLAN_EID_WAPI:
14319 /* Setting WAPI Mode to ON=1 */
14320 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014321 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014322 tmp = (u16 *) ie;
14323 tmp = tmp + 2; /* Skip element Id and Len, Version */
14324 akmsuiteCount = WPA_GET_LE16(tmp);
14325 tmp = tmp + 1;
14326 akmlist = (int *)(tmp);
14327 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
14328 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
14329 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014330 hdd_err("Invalid akmSuite count: %u",
14331 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014332 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333 return -EINVAL;
14334 }
14335
14336 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014337 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014338 pAdapter->wapi_info.wapiAuthMode =
14339 WAPI_AUTH_MODE_PSK;
14340 }
14341 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014342 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014343 pAdapter->wapi_info.wapiAuthMode =
14344 WAPI_AUTH_MODE_CERT;
14345 }
14346 break;
14347#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014348 case DOT11F_EID_SUPPOPERATINGCLASSES:
14349 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014350 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014351 status = wlan_hdd_add_assoc_ie(pWextState,
14352 genie - 2, eLen + 2);
14353 if (status)
14354 return status;
14355 break;
14356 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014357 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014358 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014359 /* when Unknown IE is received we break
14360 * and continue to the next IE in the buffer
14361 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014362 break;
14363 }
14364 genie += eLen;
14365 remLen -= eLen;
14366 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367 return 0;
14368}
14369
14370/**
14371 * hdd_is_wpaie_present() - check for WPA ie
14372 * @ie: Pointer to ie
14373 * @ie_len: Ie length
14374 *
14375 * Parse the received IE to find the WPA IE
14376 *
14377 * Return: true if wpa ie is found else false
14378 */
14379static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
14380{
14381 uint8_t eLen = 0;
14382 uint16_t remLen = ie_len;
14383 uint8_t elementId = 0;
14384
14385 while (remLen >= 2) {
14386 elementId = *ie++;
14387 eLen = *ie++;
14388 remLen -= 2;
14389 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014390 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014391 return false;
14392 }
14393 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
14394 /* OUI - 0x00 0X50 0XF2
14395 * WPA Information Element - 0x01
14396 * WPA version - 0x01
14397 */
14398 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
14399 return true;
14400 }
14401 ie += eLen;
14402 remLen -= eLen;
14403 }
14404 return false;
14405}
14406
14407/**
14408 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
14409 * @pAdapter: Pointer to adapter
14410 * @req: Pointer to security parameters
14411 *
14412 * Return: 0 for success, non-zero for failure
14413 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014414static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
14415 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014416{
14417 int status = 0;
14418 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14419 ENTER();
14420
14421 /*set wpa version */
14422 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
14423
14424 if (req->crypto.wpa_versions) {
14425 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
14426 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
14427 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
14428 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14429 }
14430 }
14431
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014432 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014433
14434 /*set authentication type */
14435 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
14436
14437 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014438 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014439 return status;
14440 }
14441
14442 /*set key mgmt type */
14443 if (req->crypto.n_akm_suites) {
14444 status =
14445 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
14446 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014447 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014448 return status;
14449 }
14450 }
14451
14452 /*set pairwise cipher type */
14453 if (req->crypto.n_ciphers_pairwise) {
14454 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
14455 req->crypto.
14456 ciphers_pairwise[0],
14457 true);
14458 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014459 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014460 return status;
14461 }
14462 } else {
14463 /*Reset previous cipher suite to none */
14464 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14465 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014466 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014467 return status;
14468 }
14469 }
14470
14471 /*set group cipher type */
14472 status =
14473 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14474 false);
14475
14476 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014477 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014478 return status;
14479 }
14480#ifdef WLAN_FEATURE_11W
14481 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14482#endif
14483
14484 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14485 if (req->ie_len) {
14486 status =
14487 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14488 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014489 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014490 return status;
14491 }
14492 }
14493
14494 /*incase of WEP set default key information */
14495 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014496 u8 key_len = req->key_len;
14497 u8 key_idx = req->key_idx;
14498
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014499 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14500 || (WLAN_CIPHER_SUITE_WEP104 ==
14501 req->crypto.ciphers_pairwise[0])
14502 ) {
14503 if (IW_AUTH_KEY_MGMT_802_1X
14504 ==
14505 (pWextState->
14506 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014507 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014508 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014509 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014510
Jeff Johnson68755312017-02-10 11:46:55 -080014511 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14512 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014513 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014514 key_idx, key_len);
14515 qdf_mem_copy(&pWextState->roamProfile.
14516 Keys.
14517 KeyMaterial[key_idx][0],
14518 req->key, key_len);
14519 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014520 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014521 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014522 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523 }
14524 }
14525 }
14526
14527 return status;
14528}
14529
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014530int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014531{
14532 unsigned long rc;
14533 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014534 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014535 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014536
14537 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014538 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14539 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014540 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014541 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14542 }
14543 /*
14544 * If firmware has already started roaming process, driver
14545 * needs to defer the processing of this disconnect request.
14546 *
14547 */
14548 if (hdd_is_roaming_in_progress(pAdapter)) {
14549 /*
14550 * Defer the disconnect action until firmware roaming
14551 * result is received. If STA is in connected state after
14552 * that, send the disconnect command to CSR, otherwise
14553 * CSR would have already sent disconnect event to upper
14554 * layer.
14555 */
14556
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014557 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014558 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14559 pAdapter->cfg80211_disconnect_reason =
14560 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14561 return 0;
14562 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014563
Jeff Johnson9edf9572016-10-03 15:24:49 -070014564 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014565 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14566 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14567 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014568 hdd_conn_set_connection_state(pAdapter,
14569 eConnectionState_Disconnecting);
14570 /* Issue disconnect to CSR */
14571 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014572
14573 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14574 pAdapter->sessionId,
14575 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14576 /*
14577 * Wait here instead of returning directly, this will block the
14578 * next connect command and allow processing of the scan for
14579 * ssid and the previous connect command in CSR. Else we might
14580 * hit some race conditions leading to SME and HDD out of sync.
14581 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014582 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014583 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014584 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014585 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014586 (int)status);
14587 pHddStaCtx->staDebugState = status;
14588 result = -EINVAL;
14589 goto disconnected;
14590 }
14591
14592 rc = wait_for_completion_timeout(
14593 &pAdapter->disconnect_comp_var,
14594 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014595 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014596 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014597 pAdapter->sessionId, pHddStaCtx->staDebugState);
14598 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014599 }
14600 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014601 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014602 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014603 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014604 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014605 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014606 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014607 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014608 }
14609 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014610disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014611 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14612 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014613}
14614
14615/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014616 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14617 * @adapter: Pointer to the HDD adapter
14618 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014619 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014620 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014621 * This function will start reassociation if prev_bssid is set and bssid/
14622 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014623 *
Naveen Rawat07332902016-07-27 09:13:17 -070014624 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014625 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014626#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14627 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014628static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14629 struct cfg80211_connect_params *req,
14630 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014631{
Naveen Rawat07332902016-07-27 09:13:17 -070014632 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014633 const uint8_t *bssid = NULL;
14634 uint16_t channel = 0;
Arif Hussain43354e62017-05-24 11:24:25 -070014635 hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014636
14637 if (req->bssid)
14638 bssid = req->bssid;
14639 else if (req->bssid_hint)
14640 bssid = req->bssid_hint;
14641
14642 if (req->channel)
14643 channel = req->channel->hw_value;
14644 else if (req->channel_hint)
14645 channel = req->channel_hint->hw_value;
14646
14647 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014648 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014649 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014650 channel, MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070014651 /*
14652 * Save BSSID in a separate variable as
14653 * pRoamProfile's BSSID is getting zeroed out in the
14654 * association process. In case of join failure
14655 * we should send valid BSSID to supplicant
14656 */
14657 qdf_mem_copy(wext_state->req_bssId.bytes, bssid,
14658 QDF_MAC_ADDR_SIZE);
14659
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014660 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014661 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014662 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014663 }
Naveen Rawat07332902016-07-27 09:13:17 -070014664 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014665}
14666#else
Naveen Rawat07332902016-07-27 09:13:17 -070014667static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14668 struct cfg80211_connect_params *req,
14669 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014670{
Naveen Rawat07332902016-07-27 09:13:17 -070014671 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014672}
14673#endif
14674
14675/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014676 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14677 * @wiphy: Pointer to wiphy
14678 * @dev: Pointer to network device
14679 * @req: Pointer to cfg80211 connect request
14680 *
14681 * This function is used to start the association process
14682 *
14683 * Return: 0 for success, non-zero for failure
14684 */
14685static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14686 struct net_device *ndev,
14687 struct cfg80211_connect_params *req)
14688{
14689 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014690 u16 channel;
14691#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14692 const u8 *bssid_hint = req->bssid_hint;
14693#else
14694 const u8 *bssid_hint = NULL;
14695#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014696 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14697 hdd_context_t *pHddCtx;
14698
14699 ENTER();
14700
Anurag Chouhan6d760662016-02-20 16:05:43 +053014701 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014702 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014703 return -EINVAL;
14704 }
14705
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014706 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14707 hdd_err("invalid session id: %d", pAdapter->sessionId);
14708 return -EINVAL;
14709 }
14710
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014711 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014712 TRACE_CODE_HDD_CFG80211_CONNECT,
14713 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014714 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014715 hdd_device_mode_to_string(pAdapter->device_mode),
14716 pAdapter->device_mode);
14717
Krunal Sonib4326f22016-03-10 13:05:51 -080014718 if (pAdapter->device_mode != QDF_STA_MODE &&
14719 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014720 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014721 hdd_device_mode_to_string(pAdapter->device_mode),
14722 pAdapter->device_mode);
14723 return -EINVAL;
14724 }
14725
14726 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14727 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014728 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014729 return -EINVAL;
14730 }
14731
14732 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014733 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014734 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014735
Naveen Rawat07332902016-07-27 09:13:17 -070014736 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014737 return status;
14738
Agrawal Ashishf156e942016-08-04 14:54:47 +053014739 /* Try disconnecting if already in connected state */
14740 status = wlan_hdd_try_disconnect(pAdapter);
14741 if (0 > status) {
14742 hdd_err("Failed to disconnect the existing connection");
14743 return -EALREADY;
14744 }
14745
14746 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014747 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014748 bool ok;
14749
14750 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14751 pHddCtx->hdd_psoc,
14752 req->channel->hw_value,
14753 &ok)) {
14754 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14755 req->channel->hw_value);
14756 return -EINVAL;
14757 }
14758 /**
14759 * Send connection timedout, so that Android framework does not
14760 * blacklist us.
14761 */
14762 if (!ok) {
14763 struct ieee80211_channel *chan =
14764 __ieee80211_get_channel(wiphy,
14765 wlan_chan_to_freq(req->channel->hw_value));
14766 struct cfg80211_bss *bss;
14767
14768 hdd_warn("Channel:%d not OK for DNBS",
14769 req->channel->hw_value);
14770 if (chan) {
14771 bss = hdd_cfg80211_get_bss(wiphy,
14772 chan,
14773 req->bssid, req->ssid,
14774 req->ssid_len);
14775 if (bss) {
14776 cfg80211_assoc_timeout(ndev, bss);
14777 return -ETIMEDOUT;
14778 }
14779 }
14780 return -EINVAL;
14781 }
14782
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014783 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14784 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014785 pAdapter->device_mode),
14786 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014787 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014788 return -ECONNREFUSED;
14789 }
14790 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014791 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14792 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014793 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014794 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014795 return -ECONNREFUSED;
14796 }
14797 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014799 /*initialise security parameters */
14800 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14801
14802 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014803 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804 return status;
14805 }
14806
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014807 if (req->channel)
14808 channel = req->channel->hw_value;
14809 else
14810 channel = 0;
14811 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14812 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014813 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014814 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014815 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014816 return status;
14817 }
14818 EXIT();
14819 return status;
14820}
14821
14822/**
14823 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14824 * @wiphy: Pointer to wiphy
14825 * @dev: Pointer to network device
14826 * @req: Pointer to cfg80211 connect request
14827 *
14828 * Return: 0 for success, non-zero for failure
14829 */
14830static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14831 struct net_device *ndev,
14832 struct cfg80211_connect_params *req)
14833{
14834 int ret;
14835 cds_ssr_protect(__func__);
14836 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14837 cds_ssr_unprotect(__func__);
14838
14839 return ret;
14840}
14841
14842/**
14843 * wlan_hdd_disconnect() - hdd disconnect api
14844 * @pAdapter: Pointer to adapter
14845 * @reason: Disconnect reason code
14846 *
14847 * This function is used to issue a disconnect request to SME
14848 *
14849 * Return: 0 for success, non-zero for failure
14850 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014851static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014852{
14853 int status, result = 0;
14854 unsigned long rc;
14855 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14856 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014857 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014858 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014859
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014860 ENTER();
14861
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014862 status = wlan_hdd_validate_context(pHddCtx);
14863
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014864 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014865 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014866 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014867 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014868 status = sme_stop_roaming(hal, pAdapter->sessionId,
14869 eCsrHddIssued);
14870 }
14871 /*
14872 * If firmware has already started roaming process, driver
14873 * needs to defer the processing of this disconnect request.
14874 */
14875 if (hdd_is_roaming_in_progress(pAdapter)) {
14876 /*
14877 * Defer the disconnect action until firmware roaming
14878 * result is received. If STA is in connected state after
14879 * that, send the disconnect command to CSR, otherwise
14880 * CSR would have already sent disconnect event to upper
14881 * layer.
14882 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014883 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014884 pAdapter->defer_disconnect =
14885 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14886 pAdapter->cfg80211_disconnect_reason = reason;
14887 return 0;
14888 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014889
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014890 prev_conn_state = pHddStaCtx->conn_info.connState;
14891
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014892 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014893 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014894 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014895 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014896 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014897 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14898 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14899
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014900 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014901
14902 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14903 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014904 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14905 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014906 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014907 result = 0;
14908 goto disconnected;
14909 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14910 /*
14911 * Wait here instead of returning directly, this will block the
14912 * next connect command and allow processing of the scan for
14913 * ssid and the previous connect command in CSR. Else we might
14914 * hit some race conditions leading to SME and HDD out of sync.
14915 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014916 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014917 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014918 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014919 pHddStaCtx->staDebugState = status;
14920 result = -EINVAL;
14921 goto disconnected;
14922 }
14923 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14924 msecs_to_jiffies
14925 (WLAN_WAIT_TIME_DISCONNECT));
14926
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014927 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014928 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014929 result = -ETIMEDOUT;
14930 }
14931disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014932 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14933#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14934 /* Sending disconnect event to userspace for kernel version < 3.11
14935 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14936 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014937 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014938 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14939 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014940#endif
14941
14942 return result;
14943}
14944
14945/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014946 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14947 * @reason: ieee80211 reason code.
14948 *
14949 * This utility function helps log string conversion of reason code.
14950 *
14951 * Return: string conversion of reason code, if match found;
14952 * "Unknown" otherwise.
14953 */
14954static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14955{
14956 switch (reason) {
14957 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14958 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14959 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14960 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14961 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14962 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14963 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14964 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14965 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14966 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14967 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14968 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14969 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14970 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14971 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14972 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14973 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14974 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14975 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14976 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14977 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14978 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14979 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14980 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14981 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14982 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14983 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14984 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14985 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14986 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14987 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14988 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14989 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14990 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14991 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14992 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14993 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14994 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14995 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14996 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14997 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14998 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14999 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
15000 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
15001 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
15002 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
15003 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
15004 default:
15005 return "Unknown";
15006 }
15007}
15008
15009/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015010 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
15011 * @wiphy: Pointer to wiphy
15012 * @dev: Pointer to network device
15013 * @reason: Disconnect reason code
15014 *
15015 * This function is used to issue a disconnect request to SME
15016 *
15017 * Return: 0 for success, non-zero for failure
15018 */
15019static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
15020 struct net_device *dev, u16 reason)
15021{
15022 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15023 int status;
15024 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15025 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15026#ifdef FEATURE_WLAN_TDLS
15027 uint8_t staIdx;
15028#endif
15029
15030 ENTER();
15031
Anurag Chouhan6d760662016-02-20 16:05:43 +053015032 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015033 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015034 return -EINVAL;
15035 }
15036
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015037 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015038 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015039 return -EINVAL;
15040 }
15041
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015042 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 TRACE_CODE_HDD_CFG80211_DISCONNECT,
15044 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015045 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015046 hdd_device_mode_to_string(pAdapter->device_mode),
15047 pAdapter->device_mode, reason);
15048
15049 status = wlan_hdd_validate_context(pHddCtx);
15050
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015051 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015052 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015053
15054 /* Issue disconnect request to SME, if station is in connected state */
15055 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
15056 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
15057 eCsrRoamDisconnectReason reasonCode =
15058 eCSR_DISCONNECT_REASON_UNSPECIFIED;
15059 hdd_scaninfo_t *pScanInfo;
15060
15061 switch (reason) {
15062 case WLAN_REASON_MIC_FAILURE:
15063 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
15064 break;
15065
15066 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
15067 case WLAN_REASON_DISASSOC_AP_BUSY:
15068 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
15069 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
15070 break;
15071
15072 case WLAN_REASON_PREV_AUTH_NOT_VALID:
15073 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
15074 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
15075 break;
15076
15077 case WLAN_REASON_DEAUTH_LEAVING:
15078 reasonCode =
15079 pHddCtx->config->
15080 gEnableDeauthToDisassocMap ?
15081 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
15082 eCSR_DISCONNECT_REASON_DEAUTH;
15083 break;
15084 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
15085 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
15086 break;
15087 default:
15088 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
15089 break;
15090 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015091 pScanInfo = &pAdapter->scan_info;
15092 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015093 hdd_debug("Disconnect is in progress, Aborting Scan");
Abhishek Singh69ccb512017-04-25 11:58:16 +053015094 wlan_abort_scan(pHddCtx->hdd_pdev, INVAL_PDEV_ID,
15095 pAdapter->sessionId, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015096 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053015097 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015098#ifdef FEATURE_WLAN_TDLS
15099 /* First clean up the tdls peers if any */
15100 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
15101 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
15102 pAdapter->sessionId)
15103 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
15104 uint8_t *mac;
15105 mac =
15106 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015107 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015108 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015109 pHddCtx->tdlsConnInfo[staIdx].staId,
15110 pAdapter->sessionId,
15111 MAC_ADDR_ARRAY(mac));
15112 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
15113 (pAdapter),
15114 pAdapter->sessionId, mac);
15115 }
15116 }
Kabilan Kannanaad2f032017-05-08 13:25:37 -070015117 hdd_notify_sta_disconnect(pAdapter->sessionId,
15118 true, pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015119#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070015120 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
15121 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015122 status = wlan_hdd_disconnect(pAdapter, reasonCode);
15123 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015124 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015125 return -EINVAL;
15126 }
15127 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015128 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015129 pHddStaCtx->conn_info.connState);
15130 }
15131
15132 return status;
15133}
15134
15135/**
15136 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
15137 * @wiphy: Pointer to wiphy
15138 * @dev: Pointer to network device
15139 * @reason: Disconnect reason code
15140 *
15141 * Return: 0 for success, non-zero for failure
15142 */
15143static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
15144 struct net_device *dev, u16 reason)
15145{
15146 int ret;
15147 cds_ssr_protect(__func__);
15148 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
15149 cds_ssr_unprotect(__func__);
15150
15151 return ret;
15152}
15153
15154/**
15155 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
15156 * @pAdapter: Pointer to adapter
15157 * @param: Pointer to IBSS parameters
15158 *
15159 * This function is used to initialize the security settings in IBSS mode
15160 *
15161 * Return: 0 for success, non-zero for failure
15162 */
15163static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
15164 struct cfg80211_ibss_params
15165 *params)
15166{
15167 int status = 0;
15168 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15169 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
15170 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15171
15172 ENTER();
15173
15174 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015175 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015176 pHddStaCtx->ibss_enc_key_installed = 0;
15177
15178 if (params->ie_len && (NULL != params->ie)) {
15179 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
15180 params->ie_len, WLAN_EID_RSN)) {
15181 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
15182 encryptionType = eCSR_ENCRYPT_TYPE_AES;
15183 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
15184 tDot11fIEWPA dot11WPAIE;
15185 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15186 u8 *ie;
15187
15188 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
15189 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
15190 params->ie_len,
15191 DOT11F_EID_WPA);
15192 if (NULL != ie) {
15193 pWextState->wpaVersion =
15194 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015195 /* Unpack the WPA IE
15196 * Skip past the EID byte and length byte
15197 * and four byte WiFi OUI
15198 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015199 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053015200 &ie[2 + 4], ie[1] - 4,
15201 &dot11WPAIE, false);
15202 /*
15203 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015204 * encType for unicast cipher for
15205 * wpa-none is none
15206 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015207 encryptionType =
15208 hdd_translate_wpa_to_csr_encryption_type
15209 (dot11WPAIE.multicast_cipher);
15210 }
15211 }
15212
15213 status =
15214 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
15215 params->ie_len);
15216
15217 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015218 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015219 return status;
15220 }
15221 }
15222
15223 pWextState->roamProfile.AuthType.authType[0] =
15224 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
15225
15226 if (params->privacy) {
15227 /* Security enabled IBSS, At this time there is no information
15228 * available about the security paramters, so initialise the
15229 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
15230 * The correct security parameters will be updated later in
15231 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
15232 * set inorder enable privacy bit in beacons
15233 */
15234
15235 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
15236 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015237 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015238 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
15239 pWextState->roamProfile.EncryptionType.numEntries = 1;
15240 pWextState->roamProfile.EncryptionType.encryptionType[0] =
15241 encryptionType;
15242 return status;
15243}
15244
15245/**
15246 * __wlan_hdd_cfg80211_join_ibss() - join ibss
15247 * @wiphy: Pointer to wiphy
15248 * @dev: Pointer to network device
15249 * @param: Pointer to IBSS join parameters
15250 *
15251 * This function is used to create/join an IBSS network
15252 *
15253 * Return: 0 for success, non-zero for failure
15254 */
15255static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15256 struct net_device *dev,
15257 struct cfg80211_ibss_params *params)
15258{
15259 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15260 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15261 tCsrRoamProfile *pRoamProfile;
15262 int status;
15263 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15264 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053015265 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015266 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015267
15268 ENTER();
15269
Anurag Chouhan6d760662016-02-20 16:05:43 +053015270 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015271 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015272 return -EINVAL;
15273 }
15274
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015275 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015276 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015277 return -EINVAL;
15278 }
15279
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015280 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015281 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
15282 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015283 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015284 hdd_device_mode_to_string(pAdapter->device_mode),
15285 pAdapter->device_mode);
15286
15287 status = wlan_hdd_validate_context(pHddCtx);
15288
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015289 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015290 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015291
15292 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053015293 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015294 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
15295 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
15296 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15297 int indx;
15298
15299 /* Get channel number */
15300 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015301 params->
15302 chandef.
15303 chan->
15304 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015305
15306 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
15307 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015308 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015309 return -EOPNOTSUPP;
15310 }
15311
15312 for (indx = 0; indx < numChans; indx++) {
15313 if (channelNum == validChan[indx]) {
15314 break;
15315 }
15316 }
15317 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015318 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015319 return -EINVAL;
15320 }
15321 }
15322
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015323 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
15324 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015325 hdd_err("This concurrency combination is not allowed");
15326 return -ECONNREFUSED;
15327 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015328
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015329 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015330 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015331 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015332
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015333 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
15334 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070015335 SIR_UPDATE_REASON_JOIN_IBSS);
15336 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015337 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070015338 return -EINVAL;
15339 }
15340
15341 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015342 status = policy_mgr_wait_for_connection_update(
15343 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015344 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015345 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015346 return -EINVAL;
15347 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015348 }
15349
15350 /*Try disconnecting if already in connected state */
15351 status = wlan_hdd_try_disconnect(pAdapter);
15352 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015353 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015354 return -EALREADY;
15355 }
15356
15357 pRoamProfile = &pWextState->roamProfile;
15358
15359 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015360 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015361 return -EINVAL;
15362 }
15363
15364 /* enable selected protection checks in IBSS mode */
15365 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
15366
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015367 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015368 WNI_CFG_IBSS_ATIM_WIN_SIZE,
15369 pHddCtx->config->
15370 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015371 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015372 }
15373
15374 /* BSSID is provided by upper layers hence no need to AUTO generate */
15375 if (NULL != params->bssid) {
15376 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015377 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015378 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015379 return -EIO;
15380 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015381 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015382 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
15383 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015384 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015385 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015386 return -EIO;
15387 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053015388 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015389 }
15390 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
15391 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
15392 pRoamProfile->beaconInterval = params->beacon_interval;
15393 else {
15394 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015395 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015396 params->beacon_interval, pRoamProfile->beaconInterval);
15397 }
15398
15399 /* Set Channel */
15400 if (channelNum) {
15401 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015402 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015403 pRoamProfile->ChannelInfo.numOfChannels = 1;
15404 pHddStaCtx->conn_info.operationChannel = channelNum;
15405 pRoamProfile->ChannelInfo.ChannelList =
15406 &pHddStaCtx->conn_info.operationChannel;
15407 }
15408
15409 /* Initialize security parameters */
15410 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
15411 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015412 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015413 return status;
15414 }
15415
15416 /* Issue connect start */
15417 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
15418 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015419 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015420 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015421 operationChannel,
15422 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015423
15424 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015425 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015426 return status;
15427 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015428 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015429 return 0;
15430}
15431
15432/**
15433 * wlan_hdd_cfg80211_join_ibss() - join ibss
15434 * @wiphy: Pointer to wiphy
15435 * @dev: Pointer to network device
15436 * @param: Pointer to IBSS join parameters
15437 *
15438 * This function is used to create/join an IBSS network
15439 *
15440 * Return: 0 for success, non-zero for failure
15441 */
15442static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15443 struct net_device *dev,
15444 struct cfg80211_ibss_params *params)
15445{
15446 int ret = 0;
15447
15448 cds_ssr_protect(__func__);
15449 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
15450 cds_ssr_unprotect(__func__);
15451
15452 return ret;
15453}
15454
15455/**
15456 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
15457 * @wiphy: Pointer to wiphy
15458 * @dev: Pointer to network device
15459 *
15460 * This function is used to leave an IBSS network
15461 *
15462 * Return: 0 for success, non-zero for failure
15463 */
15464static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15465 struct net_device *dev)
15466{
15467 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15468 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15469 tCsrRoamProfile *pRoamProfile;
15470 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15471 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015472 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015473 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015474 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015475
15476 ENTER();
15477
Anurag Chouhan6d760662016-02-20 16:05:43 +053015478 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015479 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015480 return -EINVAL;
15481 }
15482
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015483 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015484 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015485 return -EINVAL;
15486 }
15487
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015488 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015489 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15490 pAdapter->sessionId,
15491 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15492 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015493 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015494 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015495
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015496 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015497 hdd_device_mode_to_string(pAdapter->device_mode),
15498 pAdapter->device_mode);
15499 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015500 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015501 return -EIO;
15502 }
15503
15504 pRoamProfile = &pWextState->roamProfile;
15505
15506 /* Issue disconnect only if interface type is set to IBSS */
15507 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015508 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015509 return -EINVAL;
15510 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015511 /* Clearing add IE of beacon */
15512 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15513 sizeof(tSirMacAddr));
15514 updateIE.smeSessionId = pAdapter->sessionId;
15515 updateIE.ieBufferlength = 0;
15516 updateIE.pAdditionIEBuffer = NULL;
15517 updateIE.append = true;
15518 updateIE.notify = true;
15519 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15520 &updateIE,
15521 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015522 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015523 }
15524
15525 /* Reset WNI_CFG_PROBE_RSP Flags */
15526 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015527
15528 /* Issue Disconnect request */
15529 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15530 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15531 pAdapter->sessionId,
15532 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015533 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015534 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015535 hal_status);
15536 return -EAGAIN;
15537 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015538
15539 /* wait for mc thread to cleanup and then return to upper stack
15540 * so by the time upper layer calls the change interface, we are
15541 * all set to proceed further
15542 */
15543 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15544 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15545 if (!rc) {
15546 hdd_err("Failed to disconnect, timed out");
15547 return -ETIMEDOUT;
15548 }
15549
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015550 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015551 return 0;
15552}
15553
15554/**
15555 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15556 * @wiphy: Pointer to wiphy
15557 * @dev: Pointer to network device
15558 *
15559 * This function is used to leave an IBSS network
15560 *
15561 * Return: 0 for success, non-zero for failure
15562 */
15563static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15564 struct net_device *dev)
15565{
15566 int ret = 0;
15567
15568 cds_ssr_protect(__func__);
15569 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15570 cds_ssr_unprotect(__func__);
15571
15572 return ret;
15573}
15574
15575/**
15576 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15577 * @wiphy: Pointer to wiphy
15578 * @changed: Parameters changed
15579 *
15580 * This function is used to set the phy parameters. RTS Threshold/FRAG
15581 * Threshold/Retry Count etc.
15582 *
15583 * Return: 0 for success, non-zero for failure
15584 */
15585static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15586 u32 changed)
15587{
15588 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15589 tHalHandle hHal = pHddCtx->hHal;
15590 int status;
15591
15592 ENTER();
15593
Anurag Chouhan6d760662016-02-20 16:05:43 +053015594 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015595 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015596 return -EINVAL;
15597 }
15598
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015599 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015600 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15601 NO_SESSION, wiphy->rts_threshold));
15602 status = wlan_hdd_validate_context(pHddCtx);
15603
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015604 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015605 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015606
15607 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15608 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15609 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15610
15611 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15612 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015613 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015614 rts_threshold);
15615 return -EINVAL;
15616 }
15617
15618 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15619 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015620 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015621 rts_threshold);
15622 return -EIO;
15623 }
15624
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015625 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015626 }
15627
15628 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15629 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15630 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15631 wiphy->frag_threshold;
15632
15633 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15634 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015635 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015636 frag_threshold);
15637 return -EINVAL;
15638 }
15639
15640 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15641 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015642 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015643 frag_threshold);
15644 return -EIO;
15645 }
15646
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015647 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015648 }
15649
15650 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15651 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15652 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15653 wiphy->retry_short : wiphy->retry_long;
15654
15655 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15656 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015657 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015658 return -EINVAL;
15659 }
15660
15661 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15662 if (0 != sme_cfg_set_int(hHal,
15663 WNI_CFG_LONG_RETRY_LIMIT,
15664 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015665 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015666 retry_value);
15667 return -EIO;
15668 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015669 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015670 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15671 if (0 != sme_cfg_set_int(hHal,
15672 WNI_CFG_SHORT_RETRY_LIMIT,
15673 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015674 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015675 retry_value);
15676 return -EIO;
15677 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015678 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015679 }
15680 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015681 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015682 return 0;
15683}
15684
15685/**
15686 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15687 * @wiphy: Pointer to wiphy
15688 * @changed: Parameters changed
15689 *
15690 * Return: 0 for success, non-zero for failure
15691 */
15692static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15693{
15694 int ret;
15695
15696 cds_ssr_protect(__func__);
15697 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15698 cds_ssr_unprotect(__func__);
15699
15700 return ret;
15701}
15702
15703/**
15704 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15705 * key
15706 * @wiphy: Pointer to wiphy
15707 * @dev: Pointer to network device
15708 * @key_index: Key index
15709 *
15710 * Return: 0
15711 */
15712static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15713 struct net_device *netdev,
15714 u8 key_index)
15715{
15716 ENTER();
15717 return 0;
15718}
15719
15720/**
15721 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15722 * wlan_hdd_set_default_mgmt_key
15723 * @wiphy: pointer to wiphy
15724 * @netdev: pointer to net_device structure
15725 * @key_index: key index
15726 *
15727 * Return: 0 on success, error number on failure
15728 */
15729static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15730 struct net_device *netdev,
15731 u8 key_index)
15732{
15733 int ret;
15734
15735 cds_ssr_protect(__func__);
15736 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15737 cds_ssr_unprotect(__func__);
15738
15739 return ret;
15740}
15741
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015742/**
15743 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15744 * @wiphy: Pointer to wiphy
15745 * @dev: Pointer to network device
15746 * @params: Pointer to tx queue parameters
15747 *
15748 * Return: 0
15749 */
15750static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15751 struct net_device *dev,
15752 struct ieee80211_txq_params *params)
15753{
15754 ENTER();
15755 return 0;
15756}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015757
15758/**
15759 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15760 * @wiphy: pointer to wiphy
15761 * @netdev: pointer to net_device structure
15762 * @params: pointer to ieee80211_txq_params
15763 *
15764 * Return: 0 on success, error number on failure
15765 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015766static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15767 struct net_device *dev,
15768 struct ieee80211_txq_params *params)
15769{
15770 int ret;
15771
15772 cds_ssr_protect(__func__);
15773 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15774 cds_ssr_unprotect(__func__);
15775
15776 return ret;
15777}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015778
15779/**
15780 * __wlan_hdd_cfg80211_del_station() - delete station v2
15781 * @wiphy: Pointer to wiphy
15782 * @param: Pointer to delete station parameter
15783 *
15784 * Return: 0 for success, non-zero for failure
15785 */
15786static
15787int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15788 struct net_device *dev,
15789 struct tagCsrDelStaParams *pDelStaParams)
15790{
15791 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15792 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015793 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015794 hdd_hostapd_state_t *hapd_state;
15795 int status;
15796 uint8_t staId;
15797 uint8_t *mac;
15798
15799 ENTER();
15800
Anurag Chouhan6d760662016-02-20 16:05:43 +053015801 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015802 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015803 return -EINVAL;
15804 }
15805
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015806 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015807 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015808 return -EINVAL;
15809 }
15810
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015811 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015812 TRACE_CODE_HDD_CFG80211_DEL_STA,
15813 pAdapter->sessionId, pAdapter->device_mode));
15814
15815 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15816 status = wlan_hdd_validate_context(pHddCtx);
15817
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015818 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015819 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015820
15821 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15822
Krunal Sonib4326f22016-03-10 13:05:51 -080015823 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15824 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015825
15826 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15827 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015828 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015829 return 0;
15830 }
15831
Anurag Chouhanc5548422016-02-24 18:33:27 +053015832 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015833 uint16_t i;
15834 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15835 if ((pAdapter->aStaInfo[i].isUsed) &&
15836 (!pAdapter->aStaInfo[i].
15837 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015838 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015839 mac,
15840 pAdapter->aStaInfo[i].
15841 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015842 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015843 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15844 hdd_ipa_wlan_evt(pAdapter,
15845 pAdapter->
15846 aStaInfo[i].
15847 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015848 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015849 mac);
15850 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015851 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015852 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015853 MAC_ADDR_ARRAY(mac));
15854
15855 if (pHddCtx->dev_dfs_cac_status ==
15856 DFS_CAC_IN_PROGRESS)
15857 goto fn_end;
15858
Wei Song2f76f642016-11-18 16:32:53 +080015859 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015860 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015861 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015862 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015863 hdd_softap_sta_deauth(pAdapter,
15864 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015865 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015866 pAdapter->aStaInfo[i].
15867 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015868 qdf_status =
15869 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015870 &hapd_state->
15871 qdf_sta_disassoc_event,
15872 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015873 if (!QDF_IS_STATUS_SUCCESS(
15874 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015875 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015876 }
15877 }
15878 }
15879 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015880 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015881 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015882 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015883 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015884 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015885 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015886 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015887 MAC_ADDR_ARRAY(mac));
15888 return -ENOENT;
15889 }
15890
15891 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15892 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015893 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015894 }
15895
15896 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15897 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015898 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015899 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015900 MAC_ADDR_ARRAY(mac));
15901 return -ENOENT;
15902 }
15903
15904 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15905
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015906 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015907 MAC_ADDR_ARRAY(mac));
15908
15909 /* Case: SAP in ACS selected DFS ch and client connected
15910 * Now Radar detected. Then if random channel is another
15911 * DFS ch then new CAC is initiated and no TX allowed.
15912 * So do not send any mgmt frames as it will timeout
15913 * during CAC.
15914 */
15915
15916 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15917 goto fn_end;
15918
Wei Song2f76f642016-11-18 16:32:53 +080015919 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015920 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15921 (pAdapter), pAdapter->sessionId,
15922 (uint8_t *)&pDelStaParams->peerMacAddr,
15923 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015924 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015925 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015926 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927 pAdapter->aStaInfo[staId].isDeauthInProgress =
15928 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015929 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015930 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015931 MAC_ADDR_ARRAY(mac));
15932 return -ENOENT;
15933 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015934 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015935 &hapd_state->
15936 qdf_sta_disassoc_event,
15937 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015938 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015939 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015940 }
15941 }
15942 }
15943
15944fn_end:
15945 EXIT();
15946 return 0;
15947}
15948
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015949#if defined(USE_CFG80211_DEL_STA_V2)
15950/**
15951 * wlan_hdd_del_station() - delete station wrapper
15952 * @adapter: pointer to the hdd adapter
15953 *
15954 * Return: None
15955 */
15956void wlan_hdd_del_station(hdd_adapter_t *adapter)
15957{
15958 struct station_del_parameters del_sta;
15959 del_sta.mac = NULL;
15960 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15961 del_sta.reason_code = eCsrForcedDeauthSta;
15962
15963 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15964 &del_sta);
15965}
15966#else
15967void wlan_hdd_del_station(hdd_adapter_t *adapter)
15968{
15969 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15970}
15971#endif
15972
15973#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015974/**
15975 * wlan_hdd_cfg80211_del_station() - delete station v2
15976 * @wiphy: Pointer to wiphy
15977 * @param: Pointer to delete station parameter
15978 *
15979 * Return: 0 for success, non-zero for failure
15980 */
15981int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15982 struct net_device *dev,
15983 struct station_del_parameters *param)
15984#else
15985/**
15986 * wlan_hdd_cfg80211_del_station() - delete station
15987 * @wiphy: Pointer to wiphy
15988 * @mac: Pointer to station mac address
15989 *
15990 * Return: 0 for success, non-zero for failure
15991 */
15992#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15993int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15994 struct net_device *dev,
15995 const uint8_t *mac)
15996#else
15997int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15998 struct net_device *dev,
15999 uint8_t *mac)
16000#endif
16001#endif
16002{
16003 int ret;
16004 struct tagCsrDelStaParams delStaParams;
16005
16006 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080016007#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016008 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080016009 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016010 return -EINVAL;
16011 }
16012 wlansap_populate_del_sta_params(param->mac, param->reason_code,
16013 param->subtype, &delStaParams);
16014#else
16015 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
16016 (SIR_MAC_MGMT_DEAUTH >> 4),
16017 &delStaParams);
16018#endif
16019 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
16020 cds_ssr_unprotect(__func__);
16021
16022 return ret;
16023}
16024
16025/**
16026 * __wlan_hdd_cfg80211_add_station() - add station
16027 * @wiphy: Pointer to wiphy
16028 * @mac: Pointer to station mac address
16029 * @pmksa: Pointer to add station parameter
16030 *
16031 * Return: 0 for success, non-zero for failure
16032 */
16033static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16034 struct net_device *dev,
16035 const uint8_t *mac,
16036 struct station_parameters *params)
16037{
16038 int status = -EPERM;
16039#ifdef FEATURE_WLAN_TDLS
16040 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16041 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16042 u32 mask, set;
16043
16044 ENTER();
16045
Anurag Chouhan6d760662016-02-20 16:05:43 +053016046 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016047 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016048 return -EINVAL;
16049 }
16050
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016051 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016052 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016053 return -EINVAL;
16054 }
16055
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016056 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016057 TRACE_CODE_HDD_CFG80211_ADD_STA,
16058 pAdapter->sessionId, params->listen_interval));
16059
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016060 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016061 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016062
16063 mask = params->sta_flags_mask;
16064
16065 set = params->sta_flags_set;
16066
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016067 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016068 MAC_ADDR_ARRAY(mac));
16069
16070 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
16071 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080016072#if defined(CONVERGED_TDLS_ENABLE)
16073 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
16074 dev, mac);
16075#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016076 status =
16077 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080016078#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016079 }
16080 }
16081#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016082 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016083 return status;
16084}
16085
16086/**
16087 * wlan_hdd_cfg80211_add_station() - add station
16088 * @wiphy: Pointer to wiphy
16089 * @mac: Pointer to station mac address
16090 * @pmksa: Pointer to add station parameter
16091 *
16092 * Return: 0 for success, non-zero for failure
16093 */
16094#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
16095static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16096 struct net_device *dev,
16097 const uint8_t *mac,
16098 struct station_parameters *params)
16099#else
16100static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16101 struct net_device *dev, uint8_t *mac,
16102 struct station_parameters *params)
16103#endif
16104{
16105 int ret;
16106
16107 cds_ssr_protect(__func__);
16108 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
16109 cds_ssr_unprotect(__func__);
16110
16111 return ret;
16112}
16113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016114/**
16115 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
16116 * @wiphy: Pointer to wiphy
16117 * @dev: Pointer to network device
16118 * @pmksa: Pointer to set pmksa parameter
16119 *
16120 * Return: 0 for success, non-zero for failure
16121 */
16122static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
16123 struct net_device *dev,
16124 struct cfg80211_pmksa *pmksa)
16125{
16126 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16127 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16128 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016129 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016130 int status;
16131 tPmkidCacheInfo pmk_id;
16132
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016133 ENTER();
16134
Anurag Chouhan6d760662016-02-20 16:05:43 +053016135 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016136 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016137 return -EINVAL;
16138 }
16139
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016140 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016141 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016142 return -EINVAL;
16143 }
16144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016145 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016146 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016147 return -EINVAL;
16148 }
16149
16150 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016151 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016152 pmksa->bssid, pmksa->pmkid);
16153 return -EINVAL;
16154 }
16155
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016156 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016157 MAC_ADDR_ARRAY(pmksa->bssid));
16158
16159 status = wlan_hdd_validate_context(pHddCtx);
16160
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016161 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016162 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016163
16164 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16165
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016166 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
16167 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016168
16169 /* Add to the PMKSA ID Cache in CSR */
16170 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
16171 &pmk_id, 1, false);
16172
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016173 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016174 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
16175 pAdapter->sessionId, result));
16176
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016177 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016178 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016179}
16180
16181/**
16182 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
16183 * @wiphy: Pointer to wiphy
16184 * @dev: Pointer to network device
16185 * @pmksa: Pointer to set pmksa parameter
16186 *
16187 * Return: 0 for success, non-zero for failure
16188 */
16189static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
16190 struct net_device *dev,
16191 struct cfg80211_pmksa *pmksa)
16192{
16193 int ret;
16194
16195 cds_ssr_protect(__func__);
16196 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
16197 cds_ssr_unprotect(__func__);
16198
16199 return ret;
16200}
16201
16202/**
16203 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16204 * @wiphy: Pointer to wiphy
16205 * @dev: Pointer to network device
16206 * @pmksa: Pointer to pmksa parameter
16207 *
16208 * Return: 0 for success, non-zero for failure
16209 */
16210static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16211 struct net_device *dev,
16212 struct cfg80211_pmksa *pmksa)
16213{
16214 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16215 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16216 tHalHandle halHandle;
16217 int status = 0;
16218
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016219 ENTER();
16220
Anurag Chouhan6d760662016-02-20 16:05:43 +053016221 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016222 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016223 return -EINVAL;
16224 }
16225
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016226 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16227 hdd_err("invalid session id: %d", pAdapter->sessionId);
16228 return -EINVAL;
16229 }
16230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016231 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016232 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016233 return -EINVAL;
16234 }
16235
16236 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016237 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016238 return -EINVAL;
16239 }
16240
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016241 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016242 MAC_ADDR_ARRAY(pmksa->bssid));
16243
16244 status = wlan_hdd_validate_context(pHddCtx);
16245
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016246 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016247 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016248
16249 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16250
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016251 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016252 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
16253 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016254 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016255 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016256 sme_roam_del_pmkid_from_cache(halHandle,
16257 pAdapter->sessionId, pmksa->bssid,
16258 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016259 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016260 MAC_ADDR_ARRAY(pmksa->bssid));
16261 status = -EINVAL;
16262 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016263 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016264 return status;
16265}
16266
16267/**
16268 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16269 * @wiphy: Pointer to wiphy
16270 * @dev: Pointer to network device
16271 * @pmksa: Pointer to pmksa parameter
16272 *
16273 * Return: 0 for success, non-zero for failure
16274 */
16275static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16276 struct net_device *dev,
16277 struct cfg80211_pmksa *pmksa)
16278{
16279 int ret;
16280
16281 cds_ssr_protect(__func__);
16282 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
16283 cds_ssr_unprotect(__func__);
16284
16285 return ret;
16286
16287}
16288
16289/**
16290 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16291 * @wiphy: Pointer to wiphy
16292 * @dev: Pointer to network device
16293 *
16294 * Return: 0 for success, non-zero for failure
16295 */
16296static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16297 struct net_device *dev)
16298{
16299 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16300 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16301 tHalHandle halHandle;
16302 int status = 0;
16303
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016304 ENTER();
16305
Anurag Chouhan6d760662016-02-20 16:05:43 +053016306 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016307 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016308 return -EINVAL;
16309 }
16310
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016311 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16312 hdd_err("invalid session id: %d", pAdapter->sessionId);
16313 return -EINVAL;
16314 }
16315
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016316 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016317
16318 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16319 status = wlan_hdd_validate_context(pHddCtx);
16320
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016321 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016322 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016323
16324 /* Retrieve halHandle */
16325 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16326
16327 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016328 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016329 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
16330 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016331 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016332 status = -EINVAL;
16333 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016334 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016335 return status;
16336}
16337
16338/**
16339 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16340 * @wiphy: Pointer to wiphy
16341 * @dev: Pointer to network device
16342 *
16343 * Return: 0 for success, non-zero for failure
16344 */
16345static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16346 struct net_device *dev)
16347{
16348 int ret;
16349
16350 cds_ssr_protect(__func__);
16351 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
16352 cds_ssr_unprotect(__func__);
16353
16354 return ret;
16355}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016356
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016357#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016358/**
16359 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16360 * @wiphy: Pointer to wiphy
16361 * @dev: Pointer to network device
16362 * @ftie: Pointer to fast transition ie parameter
16363 *
16364 * Return: 0 for success, non-zero for failure
16365 */
16366static int
16367__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16368 struct net_device *dev,
16369 struct cfg80211_update_ft_ies_params *ftie)
16370{
16371 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16372 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16373 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16374 int status;
16375
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016376 ENTER();
16377
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016378 status = wlan_hdd_validate_context(hdd_ctx);
16379 if (status)
16380 return status;
16381
Anurag Chouhan6d760662016-02-20 16:05:43 +053016382 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016383 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016384 return -EINVAL;
16385 }
16386
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016387 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16388 hdd_err("invalid session id: %d", pAdapter->sessionId);
16389 return -EINVAL;
16390 }
16391
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016392 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016393 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
16394 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
16395 /* Added for debug on reception of Re-assoc Req. */
16396 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016397 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016398 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016399 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016400 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016401 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016402 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016403
16404 /* Pass the received FT IEs to SME */
16405 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
16406 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016407 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016408 return 0;
16409}
16410
16411/**
16412 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16413 * @wiphy: Pointer to wiphy
16414 * @dev: Pointer to network device
16415 * @ftie: Pointer to fast transition ie parameter
16416 *
16417 * Return: 0 for success, non-zero for failure
16418 */
16419static int
16420wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16421 struct net_device *dev,
16422 struct cfg80211_update_ft_ies_params *ftie)
16423{
16424 int ret;
16425
16426 cds_ssr_protect(__func__);
16427 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
16428 cds_ssr_unprotect(__func__);
16429
16430 return ret;
16431}
16432#endif
16433
Mukul Sharma3d36c392017-01-18 18:39:12 +053016434void wlan_hdd_cfg80211_update_replay_counter_callback(
16435 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
16436
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016437{
Mukul Sharma3d36c392017-01-18 18:39:12 +053016438 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
16439 uint8_t temp_replay_counter[8];
16440 int i;
16441 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016442
16443 ENTER();
16444
Mukul Sharma3d36c392017-01-18 18:39:12 +053016445 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016446 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016447 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016448 }
16449
Mukul Sharma3d36c392017-01-18 18:39:12 +053016450 if (!gtk_rsp_param) {
16451 hdd_err("gtk_rsp_param is Null");
16452 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016453 }
16454
Mukul Sharma3d36c392017-01-18 18:39:12 +053016455 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016456 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016457 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016458 }
16459
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016460 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016461 gtk_rsp_param->replay_counter);
16462 /* convert little to big endian since supplicant works on big endian */
16463 p = (uint8_t *)&gtk_rsp_param->replay_counter;
16464 for (i = 0; i < 8; i++)
16465 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016466
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016467 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016468 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080016469 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016470 gtk_rsp_param->bssid.bytes,
16471 temp_replay_counter, GFP_KERNEL);
16472out:
16473 EXIT();
16474
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016475}
16476
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016477static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016478int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016479 struct net_device *dev,
16480 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016481{
16482 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016483 int result, i;
16484 struct pmo_gtk_req *gtk_req = NULL;
16485 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16486 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016487 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016488
16489 ENTER();
16490
Anurag Chouhan6d760662016-02-20 16:05:43 +053016491 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016492 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016493 result = -EINVAL;
16494 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016495 }
16496
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016497 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16498 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016499 result = -EINVAL;
16500 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016501 }
16502
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016503 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016504 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16505 pAdapter->sessionId, pAdapter->device_mode));
16506
Mukul Sharma3d36c392017-01-18 18:39:12 +053016507 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016508 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016509 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016510
Mukul Sharma3d36c392017-01-18 18:39:12 +053016511 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16512 if (!gtk_req) {
16513 hdd_err("cannot allocate gtk_req");
16514 result = -ENOMEM;
16515 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016516 }
16517
Mukul Sharma3d36c392017-01-18 18:39:12 +053016518 /* convert big to little endian since driver work on little endian */
16519 buf = (uint8_t *)&gtk_req->replay_counter;
16520 for (i = 0; i < 8; i++)
16521 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016522
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016523 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016524 gtk_req->replay_counter);
16525 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16526 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16527 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16528 if (status != QDF_STATUS_SUCCESS) {
16529 hdd_err("Failed to cache GTK Offload");
16530 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016531 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016532out:
16533 if (gtk_req)
16534 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016535 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016537 return result;
16538}
16539
16540/**
16541 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16542 * @wiphy: Pointer to wiphy
16543 * @dev: Pointer to network device
16544 * @data: Pointer to rekey data
16545 *
16546 * This function is used to offload GTK rekeying job to the firmware.
16547 *
16548 * Return: 0 for success, non-zero for failure
16549 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016550static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016551int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16552 struct net_device *dev,
16553 struct cfg80211_gtk_rekey_data *data)
16554{
16555 int ret;
16556
16557 cds_ssr_protect(__func__);
16558 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16559 cds_ssr_unprotect(__func__);
16560
16561 return ret;
16562}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016563
16564/**
16565 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16566 * @wiphy: Pointer to wiphy
16567 * @dev: Pointer to network device
16568 * @param: Pointer to access control parameter
16569 *
16570 * Return: 0 for success, non-zero for failure
16571 */
16572static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16573 struct net_device *dev,
16574 const struct cfg80211_acl_data *params)
16575{
16576 int i;
16577 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16578 hdd_hostapd_state_t *pHostapdState;
16579 tsap_Config_t *pConfig;
16580 v_CONTEXT_t p_cds_context = NULL;
16581 hdd_context_t *pHddCtx;
16582 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016583 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016584
16585 ENTER();
16586
Anurag Chouhan6d760662016-02-20 16:05:43 +053016587 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016588 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016589 return -EINVAL;
16590 }
16591
16592 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016593 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016594 return -EINVAL;
16595 }
16596
16597 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16598 status = wlan_hdd_validate_context(pHddCtx);
16599
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016600 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016601 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016602
16603 p_cds_context = pHddCtx->pcds_context;
16604 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16605
16606 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016607 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016608 return -EINVAL;
16609 }
16610
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016611 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016612 params->n_acl_entries);
16613
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016614 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016615 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16616 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016617 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016618 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16619
16620 /* default value */
16621 pConfig->num_accept_mac = 0;
16622 pConfig->num_deny_mac = 0;
16623
16624 /**
16625 * access control policy
16626 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16627 * listed in hostapd.deny file.
16628 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16629 * listed in hostapd.accept file.
16630 */
16631 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16632 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16633 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16634 params->acl_policy) {
16635 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16636 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016637 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016638 params->acl_policy);
16639 return -ENOTSUPP;
16640 }
16641
16642 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16643 pConfig->num_accept_mac = params->n_acl_entries;
16644 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016645 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016646 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016647 MAC_ADDR_ARRAY(
16648 params->mac_addrs[i].addr));
16649
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016650 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016651 params->mac_addrs[i].addr,
16652 sizeof(qcmacaddr));
16653 }
16654 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16655 pConfig->num_deny_mac = params->n_acl_entries;
16656 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016657 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016658 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016659 MAC_ADDR_ARRAY(
16660 params->mac_addrs[i].addr));
16661
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016662 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016663 params->mac_addrs[i].addr,
16664 sizeof(qcmacaddr));
16665 }
16666 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016667 qdf_status = wlansap_set_mac_acl(
16668 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016669 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016670 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016671 return -EINVAL;
16672 }
16673 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016674 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016675 hdd_device_mode_to_string(pAdapter->device_mode),
16676 pAdapter->device_mode);
16677 return -EINVAL;
16678 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016679 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016680 return 0;
16681}
16682
16683/**
16684 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16685 * __wlan_hdd_cfg80211_set_mac_acl
16686 * @wiphy: pointer to wiphy structure
16687 * @dev: pointer to net_device
16688 * @params: pointer to cfg80211_acl_data
16689 *
16690 * Return; 0 on success, error number otherwise
16691 */
16692static int
16693wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16694 struct net_device *dev,
16695 const struct cfg80211_acl_data *params)
16696{
16697 int ret;
16698
16699 cds_ssr_protect(__func__);
16700 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16701 cds_ssr_unprotect(__func__);
16702
16703 return ret;
16704}
16705
16706#ifdef WLAN_NL80211_TESTMODE
16707#ifdef FEATURE_WLAN_LPHB
16708/**
16709 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16710 * @pHddCtx: Pointer to hdd context
16711 * @lphbInd: Pointer to low power heart beat indication parameter
16712 *
16713 * Return: none
16714 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016715static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016716 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016717{
16718 struct sk_buff *skb;
16719
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016720 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016721
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016722 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016723 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016724
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016725 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016726 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016727 return;
16728 }
16729
16730 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016731 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016732 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016733 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016734 return;
16735 }
16736
16737 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016738 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016739 goto nla_put_failure;
16740 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016741 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016742 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016743 goto nla_put_failure;
16744 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016745 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16746 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016747 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016748 goto nla_put_failure;
16749 }
16750 cfg80211_testmode_event(skb, GFP_ATOMIC);
16751 return;
16752
16753nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016754 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016755 kfree_skb(skb);
16756
16757 return;
16758}
16759#endif /* FEATURE_WLAN_LPHB */
16760
16761/**
16762 * __wlan_hdd_cfg80211_testmode() - test mode
16763 * @wiphy: Pointer to wiphy
16764 * @data: Data pointer
16765 * @len: Data length
16766 *
16767 * Return: 0 for success, non-zero for failure
16768 */
16769static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16770 void *data, int len)
16771{
16772 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16773 int err;
16774 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16775
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016776 ENTER();
16777
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016778 err = wlan_hdd_validate_context(pHddCtx);
16779 if (err)
16780 return err;
16781
16782 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16783 len, wlan_hdd_tm_policy);
16784 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016785 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016786 return err;
16787 }
16788
16789 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016790 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016791 return -EINVAL;
16792 }
16793
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016794 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016795 TRACE_CODE_HDD_CFG80211_TESTMODE,
16796 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016797 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16798#ifdef FEATURE_WLAN_LPHB
16799 /* Low Power Heartbeat configuration request */
16800 case WLAN_HDD_TM_CMD_WLAN_HB:
16801 {
16802 int buf_len;
16803 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016804 struct pmo_lphb_req *hb_params = NULL;
16805 struct pmo_lphb_req *hb_params_temp = NULL;
16806 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016807
16808 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016809 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016810 return -EINVAL;
16811 }
16812
16813 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16814 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16815
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016816 hb_params_temp = (struct pmo_lphb_req *) buf;
16817 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16818 && (hb_params_temp->params.lphb_tcp_params.
16819 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016820 return -EINVAL;
16821
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016822 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16823 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016824 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016825 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016826 return -ENOMEM;
16827 }
16828
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016829 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016830 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16831 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016832 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016833 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016834 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016835
16836 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016837 return 0;
16838 }
16839#endif /* FEATURE_WLAN_LPHB */
16840
16841#if defined(QCA_WIFI_FTM)
16842 case WLAN_HDD_TM_CMD_WLAN_FTM:
16843 {
16844 int buf_len;
16845 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016846 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016847 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016848 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016849 return -EINVAL;
16850 }
16851
16852 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16853 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16854
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016855 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016856
16857 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16858
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016859 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016860 err = -EBUSY;
16861 break;
16862 }
16863#endif
16864
16865 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016866 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016867 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16868 return -EOPNOTSUPP;
16869 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016870 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016871 return err;
16872}
16873
16874/**
16875 * wlan_hdd_cfg80211_testmode() - test mode
16876 * @wiphy: Pointer to wiphy
16877 * @dev: Pointer to network device
16878 * @data: Data pointer
16879 * @len: Data length
16880 *
16881 * Return: 0 for success, non-zero for failure
16882 */
16883static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16884#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16885 struct wireless_dev *wdev,
16886#endif
16887 void *data, int len)
16888{
16889 int ret;
16890
16891 cds_ssr_protect(__func__);
16892 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16893 cds_ssr_unprotect(__func__);
16894
16895 return ret;
16896}
16897
16898#if defined(QCA_WIFI_FTM)
16899/**
16900 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16901 * @buf: Pointer to buffer
16902 * @buf_len: Buffer length
16903 *
16904 * Return: none
16905 */
16906void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16907{
16908 struct sk_buff *skb;
16909 hdd_context_t *hdd_ctx;
16910
16911 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016912 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016913 return;
16914 }
16915
Anurag Chouhan6d760662016-02-20 16:05:43 +053016916 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016917 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016918 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016919 return;
16920 }
16921
16922 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16923 buf_len, GFP_KERNEL);
16924 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016925 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016926 return;
16927 }
16928
16929 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16930 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16931 goto nla_put_failure;
16932
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016933 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016934
16935 cfg80211_testmode_event(skb, GFP_KERNEL);
16936 return;
16937
16938nla_put_failure:
16939 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016940 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016941}
16942#endif
16943#endif /* CONFIG_NL80211_TESTMODE */
16944
16945#ifdef QCA_HT_2040_COEX
16946/**
16947 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16948 * @wiphy: Pointer to wiphy
16949 * @dev: Pointer to network device
16950 * @chandef: Pointer to channel definition parameter
16951 *
16952 * Return: 0 for success, non-zero for failure
16953 */
16954static int
16955__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16956 struct net_device *dev,
16957 struct cfg80211_chan_def *chandef)
16958{
16959 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16960 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016961 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016962 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016963 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016964
Anurag Chouhan6d760662016-02-20 16:05:43 +053016965 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016966 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016967 return -EINVAL;
16968 }
16969
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016970 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16971 hdd_err("invalid session id: %d", pAdapter->sessionId);
16972 return -EINVAL;
16973 }
16974
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016975 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16976 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016977 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016978 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016979
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016980 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016981 sme_get_config_param(pHddCtx->hHal, &sme_config);
16982 switch (chandef->width) {
16983 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016984 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016985 if (sme_config.csrConfig.channelBondingMode24GHz !=
16986 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16987 sme_config.csrConfig.channelBondingMode24GHz =
16988 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16989 sme_update_config(pHddCtx->hHal, &sme_config);
16990 cbModeChange = true;
16991 }
16992 break;
16993
16994 case NL80211_CHAN_WIDTH_40:
16995 if (sme_config.csrConfig.channelBondingMode24GHz ==
16996 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16997 if (NL80211_CHAN_HT40MINUS ==
16998 cfg80211_get_chandef_type(chandef))
16999 sme_config.csrConfig.channelBondingMode24GHz =
17000 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
17001 else
17002 sme_config.csrConfig.channelBondingMode24GHz =
17003 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
17004 sme_update_config(pHddCtx->hHal, &sme_config);
17005 cbModeChange = true;
17006 }
17007 break;
17008
17009 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017010 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017011 return -EINVAL;
17012 }
17013
17014 if (!cbModeChange)
17015 return 0;
17016
Krunal Sonib4326f22016-03-10 13:05:51 -080017017 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017018 return 0;
17019
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017020 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017021 sme_config.csrConfig.channelBondingMode24GHz);
17022
17023 /* Change SAP ht2040 mode */
17024 status = hdd_set_sap_ht2040_mode(pAdapter,
17025 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017026 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017027 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017028 return -EINVAL;
17029 }
17030
17031 return 0;
17032}
17033
17034/**
17035 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
17036 * @wiphy: Pointer to wiphy
17037 * @dev: Pointer to network device
17038 * @chandef: Pointer to channel definition parameter
17039 *
17040 * Return: 0 for success, non-zero for failure
17041 */
17042static int
17043wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
17044 struct net_device *dev,
17045 struct cfg80211_chan_def *chandef)
17046{
17047 int ret;
17048
17049 cds_ssr_protect(__func__);
17050 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
17051 cds_ssr_unprotect(__func__);
17052
17053 return ret;
17054}
17055#endif
17056
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017057#ifdef CHANNEL_SWITCH_SUPPORTED
17058/**
17059 * __wlan_hdd_cfg80211_channel_switch()- function to switch
17060 * channel in SAP/GO
17061 * @wiphy: wiphy pointer
17062 * @dev: dev pointer.
17063 * @csa_params: Change channel params
17064 *
17065 * This function is called to switch channel in SAP/GO
17066 *
17067 * Return: 0 if success else return non zero
17068 */
17069static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
17070 struct net_device *dev,
17071 struct cfg80211_csa_settings *csa_params)
17072{
17073 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
17074 hdd_context_t *hdd_ctx;
17075 uint8_t channel;
17076 uint16_t freq;
17077 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080017078 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017079
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017080 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017081 csa_params->chandef.chan->center_freq);
17082
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017083 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
17084 hdd_err("invalid session id: %d", adapter->sessionId);
17085 return -EINVAL;
17086 }
17087
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017088 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17089 ret = wlan_hdd_validate_context(hdd_ctx);
17090
17091 if (0 != ret)
17092 return ret;
17093
Krunal Sonib4326f22016-03-10 13:05:51 -080017094 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
17095 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017096 return -ENOTSUPP;
17097
17098 freq = csa_params->chandef.chan->center_freq;
17099 channel = cds_freq_to_chan(freq);
17100
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053017101 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
17102
17103 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017104 return ret;
17105}
17106
17107/**
17108 * wlan_hdd_cfg80211_channel_switch()- function to switch
17109 * channel in SAP/GO
17110 * @wiphy: wiphy pointer
17111 * @dev: dev pointer.
17112 * @csa_params: Change channel params
17113 *
17114 * This function is called to switch channel in SAP/GO
17115 *
17116 * Return: 0 if success else return non zero
17117 */
17118static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
17119 struct net_device *dev,
17120 struct cfg80211_csa_settings *csa_params)
17121{
17122 int ret;
17123
17124 cds_ssr_protect(__func__);
17125 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
17126 cds_ssr_unprotect(__func__);
17127 return ret;
17128}
17129#endif
17130
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017131/**
17132 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
17133 * translation from NL to policy manager type
17134 * @type: Generic connection mode type defined in NL
17135 *
17136 *
17137 * This function provides the type translation
17138 *
17139 * Return: cds_con_mode enum
17140 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017141enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017142 enum nl80211_iftype type)
17143{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017144 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017145 switch (type) {
17146 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017147 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017148 break;
17149 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017150 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017151 break;
17152 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017153 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017154 break;
17155 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017156 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017157 break;
17158 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017159 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017160 break;
17161 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017162 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017163 }
17164 return mode;
17165}
17166
17167/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017168 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17169 * @wiphy: Handle to struct wiphy to get handle to module context.
17170 * @chandef: Contains information about the capture channel to be set.
17171 *
17172 * This interface is called if and only if monitor mode interface alone is
17173 * active.
17174 *
17175 * Return: 0 success or error code on failure.
17176 */
17177static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17178 struct cfg80211_chan_def *chandef)
17179{
17180 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
17181 hdd_adapter_t *adapter;
17182 hdd_station_ctx_t *sta_ctx;
17183 struct hdd_mon_set_ch_info *ch_info;
17184 QDF_STATUS status;
17185 tHalHandle hal_hdl;
17186 struct qdf_mac_addr bssid;
17187 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080017188 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017189 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017190 int ret;
17191 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
17192
17193 ENTER();
17194
17195 ret = wlan_hdd_validate_context(hdd_ctx);
17196 if (ret)
17197 return ret;
17198
17199 hal_hdl = hdd_ctx->hHal;
17200
17201 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
17202 if (!adapter)
17203 return -EIO;
17204
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017205 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017206 adapter->dev->name, chan_num, chandef->chan->center_freq);
17207
17208 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17209 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017210 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
17211 roam_profile.ChannelInfo.numOfChannels = 1;
17212 roam_profile.phyMode = ch_info->phy_mode;
17213 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017214 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017215
17216 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
17217 QDF_MAC_ADDR_SIZE);
17218
17219 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017220 /*
17221 * CDS api expects secondary channel for calculating
17222 * the channel params
17223 */
17224 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017225 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017226 if (chan_num >= 1 && chan_num <= 5)
17227 sec_ch = chan_num + 4;
17228 else if (chan_num >= 6 && chan_num <= 13)
17229 sec_ch = chan_num - 4;
17230 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017231 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
17232 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017233 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
17234 &roam_profile);
17235 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017236 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017237 status);
17238 ret = qdf_status_to_os_return(status);
17239 return ret;
17240 }
17241 EXIT();
17242 return 0;
17243}
17244
17245/**
17246 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17247 * @wiphy: Handle to struct wiphy to get handle to module context.
17248 * @chandef: Contains information about the capture channel to be set.
17249 *
17250 * This interface is called if and only if monitor mode interface alone is
17251 * active.
17252 *
17253 * Return: 0 success or error code on failure.
17254 */
17255static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17256 struct cfg80211_chan_def *chandef)
17257{
17258 int ret;
17259
17260 cds_ssr_protect(__func__);
17261 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
17262 cds_ssr_unprotect(__func__);
17263 return ret;
17264}
17265
17266/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017267 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
17268 * @adapter: pointer to adapter
17269 *
17270 * Wrapper function to clear link layer stats.
17271 * return - void
17272 */
17273void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
17274{
17275 tSirLLStatsClearReq link_layer_stats_clear_req;
17276 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
17277
Mukul Sharma491021c2016-09-29 21:39:19 +053017278 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
17279 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017280 link_layer_stats_clear_req.stopReq = 0;
17281 link_layer_stats_clear_req.reqId = 1;
17282 link_layer_stats_clear_req.staId = adapter->sessionId;
17283 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
17284
17285 return;
17286}
17287
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017288/**
17289 * hdd_process_defer_disconnect() - Handle the deferred disconnect
17290 * @adapter: HDD Adapter
17291 *
17292 * If roaming is in progress and there is a request to
17293 * disconnect the session, then it is deferred. Once
17294 * roaming is complete/aborted, then this routine is
17295 * used to resume the disconnect that was deferred
17296 *
17297 * Return: None
17298 */
17299void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
17300{
17301 switch (adapter->defer_disconnect) {
17302 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
17303 adapter->defer_disconnect = 0;
17304 wlan_hdd_disconnect(adapter,
17305 adapter->cfg80211_disconnect_reason);
17306 break;
17307 case DEFER_DISCONNECT_TRY_DISCONNECT:
17308 wlan_hdd_try_disconnect(adapter);
17309 adapter->defer_disconnect = 0;
17310 break;
17311 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017312 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017313 adapter->defer_disconnect);
17314 break;
17315 }
17316}
17317
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017318#define CNT_DIFF(cur, prev) \
17319 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
17320#define MAX_COUNT 0xffffffff
17321static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
17322 struct scan_chan_info *chan,
17323 struct scan_chan_info *info, uint32_t cmd_flag)
17324{
17325 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
17326 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
17327 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
17328
17329 mutex_lock(&hdd_ctx->chan_info_lock);
17330
17331 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
17332 qdf_mem_zero(chan, sizeof(*chan));
17333
17334 chan->freq = info->freq;
17335 chan->noise_floor = info->noise_floor;
17336 chan->clock_freq = info->clock_freq;
17337 chan->cmd_flag = info->cmd_flag;
17338 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
17339
17340 chan->rx_clear_count =
17341 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
17342
17343 chan->tx_frame_count =
17344 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
17345
17346 mutex_unlock(&hdd_ctx->chan_info_lock);
17347
17348}
17349#undef CNT_DIFF
17350#undef MAX_COUNT
17351
17352/**
17353 * wlan_hdd_chan_info_cb() - channel info callback
17354 * @chan_info: struct scan_chan_info
17355 *
17356 * Store channel info into HDD context
17357 *
17358 * Return: None.
17359 */
17360static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
17361{
17362 hdd_context_t *hdd_ctx;
17363 struct scan_chan_info *chan;
17364 uint8_t idx;
17365
17366 ENTER();
17367
17368 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17369 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
17370 hdd_err("hdd_ctx is invalid");
17371 return;
17372 }
17373
17374 if (!hdd_ctx->chan_info) {
17375 hdd_err("chan_info is NULL");
17376 return;
17377 }
17378
17379 chan = hdd_ctx->chan_info;
17380 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
17381 if (chan[idx].freq == info->freq) {
17382 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
17383 info->cmd_flag);
17384 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
17385 chan[idx].cmd_flag, chan[idx].freq,
17386 chan[idx].noise_floor,
17387 chan[idx].cycle_count, chan[idx].rx_clear_count,
17388 chan[idx].clock_freq, chan[idx].cmd_flag,
17389 chan[idx].tx_frame_count, idx);
17390 if (chan[idx].freq == 0)
17391 break;
17392
17393 }
17394 }
17395
17396 EXIT();
17397}
17398
17399/**
17400 * wlan_hdd_init_chan_info() - init chan info in hdd context
17401 * @hdd_ctx: HDD context pointer
17402 *
17403 * Return: none
17404 */
17405void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
17406{
17407 uint8_t num_2g, num_5g, index = 0;
17408
17409 if (!hdd_ctx->config->fEnableSNRMonitoring) {
17410 hdd_info("SNR monitoring is disabled");
17411 return;
17412 }
17413
17414 hdd_ctx->chan_info =
17415 qdf_mem_malloc(sizeof(struct scan_chan_info)
17416 * QDF_MAX_NUM_CHAN);
17417 if (hdd_ctx->chan_info == NULL) {
17418 hdd_err("Failed to malloc for chan info");
17419 return;
17420 }
17421 mutex_init(&hdd_ctx->chan_info_lock);
17422
17423 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
17424 for (; index < num_2g; index++) {
17425 hdd_ctx->chan_info[index].freq =
17426 hdd_channels_2_4_ghz[index].center_freq;
17427 }
17428
17429 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
17430 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017431 if (WLAN_REG_IS_11P_CH(
17432 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017433 continue;
17434 hdd_ctx->chan_info[index].freq =
17435 hdd_channels_5_ghz[index - num_2g].center_freq;
17436 }
17437 sme_set_chan_info_callback(hdd_ctx->hHal,
17438 &wlan_hdd_chan_info_cb);
17439}
17440
17441/**
17442 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
17443 * @hdd_ctx: hdd context pointer
17444 *
17445 * Return: none
17446 */
17447void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
17448{
17449 struct scan_chan_info *chan;
17450
17451 chan = hdd_ctx->chan_info;
17452 hdd_ctx->chan_info = NULL;
17453 if (chan)
17454 qdf_mem_free(chan);
17455}
17456
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017457/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017458 * struct cfg80211_ops - cfg80211_ops
17459 *
17460 * @add_virtual_intf: Add virtual interface
17461 * @del_virtual_intf: Delete virtual interface
17462 * @change_virtual_intf: Change virtual interface
17463 * @change_station: Change station
17464 * @add_beacon: Add beacon in sap mode
17465 * @del_beacon: Delete beacon in sap mode
17466 * @set_beacon: Set beacon in sap mode
17467 * @start_ap: Start ap
17468 * @change_beacon: Change beacon
17469 * @stop_ap: Stop ap
17470 * @change_bss: Change bss
17471 * @add_key: Add key
17472 * @get_key: Get key
17473 * @del_key: Delete key
17474 * @set_default_key: Set default key
17475 * @set_channel: Set channel
17476 * @scan: Scan
17477 * @connect: Connect
17478 * @disconnect: Disconnect
17479 * @join_ibss = Join ibss
17480 * @leave_ibss = Leave ibss
17481 * @set_wiphy_params = Set wiphy params
17482 * @set_tx_power = Set tx power
17483 * @get_tx_power = get tx power
17484 * @remain_on_channel = Remain on channel
17485 * @cancel_remain_on_channel = Cancel remain on channel
17486 * @mgmt_tx = Tx management frame
17487 * @mgmt_tx_cancel_wait = Cancel management tx wait
17488 * @set_default_mgmt_key = Set default management key
17489 * @set_txq_params = Set tx queue parameters
17490 * @get_station = Get station
17491 * @set_power_mgmt = Set power management
17492 * @del_station = Delete station
17493 * @add_station = Add station
17494 * @set_pmksa = Set pmksa
17495 * @del_pmksa = Delete pmksa
17496 * @flush_pmksa = Flush pmksa
17497 * @update_ft_ies = Update FT IEs
17498 * @tdls_mgmt = Tdls management
17499 * @tdls_oper = Tdls operation
17500 * @set_rekey_data = Set rekey data
17501 * @sched_scan_start = Scheduled scan start
17502 * @sched_scan_stop = Scheduled scan stop
17503 * @resume = Resume wlan
17504 * @suspend = Suspend wlan
17505 * @set_mac_acl = Set mac acl
17506 * @testmode_cmd = Test mode command
17507 * @set_ap_chanwidth = Set AP channel bandwidth
17508 * @dump_survey = Dump survey
17509 * @key_mgmt_set_pmk = Set pmk key management
17510 */
17511static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17512 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17513 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17514 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17515 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017516 .start_ap = wlan_hdd_cfg80211_start_ap,
17517 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17518 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017519 .change_bss = wlan_hdd_cfg80211_change_bss,
17520 .add_key = wlan_hdd_cfg80211_add_key,
17521 .get_key = wlan_hdd_cfg80211_get_key,
17522 .del_key = wlan_hdd_cfg80211_del_key,
17523 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17524 .scan = wlan_hdd_cfg80211_scan,
17525 .connect = wlan_hdd_cfg80211_connect,
17526 .disconnect = wlan_hdd_cfg80211_disconnect,
17527 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17528 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17529 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17530 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17531 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17532 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17533 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17534 .mgmt_tx = wlan_hdd_mgmt_tx,
17535 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17536 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17537 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017538 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017539 .get_station = wlan_hdd_cfg80211_get_station,
17540 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17541 .del_station = wlan_hdd_cfg80211_del_station,
17542 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017543 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17544 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17545 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017546#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017547 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17548#endif
17549#ifdef FEATURE_WLAN_TDLS
17550 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17551 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17552#endif
17553#ifdef WLAN_FEATURE_GTK_OFFLOAD
17554 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17555#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17556#ifdef FEATURE_WLAN_SCAN_PNO
17557 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17558 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17559#endif /*FEATURE_WLAN_SCAN_PNO */
17560 .resume = wlan_hdd_cfg80211_resume_wlan,
17561 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17562 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17563#ifdef WLAN_NL80211_TESTMODE
17564 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17565#endif
17566#ifdef QCA_HT_2040_COEX
17567 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17568#endif
17569 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017570#ifdef CHANNEL_SWITCH_SUPPORTED
17571 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17572#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017573 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017574#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17575 defined(CFG80211_ABORT_SCAN)
17576 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17577#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017578};