blob: d414051ed99187b5fe6113bdd0a890da3efa7674 [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
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764/*
765 * FUNCTION: wlan_hdd_send_avoid_freq_event
766 * This is called when wlan driver needs to send vendor specific
767 * avoid frequency range event to userspace
768 */
769int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
770 tHddAvoidFreqList *pAvoidFreqList)
771{
772 struct sk_buff *vendor_event;
773
774 ENTER();
775
776 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700777 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 return -EINVAL;
779 }
780
781 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700782 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783 return -EINVAL;
784 }
785
786 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
787 NULL,
788 sizeof(tHddAvoidFreqList),
789 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
790 GFP_KERNEL);
791 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700792 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793 return -EINVAL;
794 }
795
796 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
797 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
798
799 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
800
801 EXIT();
802 return 0;
803}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530805/**
806 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
807 * with respect to the channel passed.
808 * @chan: Channel
809 * @upper: If "true" then next channel is returned or else
810 * previous channel is returned.
811 *
812 * This function returns the next/previous adjacent-channel to
813 * the channel passed. If "upper = true" then next channel is
814 * returned else previous is returned.
815 */
816int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
817{
818 enum channel_enum ch_idx = reg_get_chan_enum(chan);
819
820 if (ch_idx == INVALID_CHANNEL)
821 return -EINVAL;
822
823 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
824 ch_idx++;
825 else if (!upper && (ch_idx > CHAN_ENUM_1))
826 ch_idx--;
827 else
828 return -EINVAL;
829
830 return WLAN_REG_CH_NUM(ch_idx);
831}
832
833/**
834 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
835 * avoided when Do_Not_Break_Stream is active.
836 * @pHddCtx: HDD Context
837 * @op_chan: AP/P2P-GO operating channel
838 *
839 * This function sends list of frequencies to be avoided when
840 * Do_Not_Break_Stream is active.
841 * To clear the avoid_frequency_list in the application,
842 * op_chan = 0 can be passed.
843 *
844 * Return: 0 on success and errno on failure
845 */
846int wlan_hdd_send_avoid_freq_for_dnbs(hdd_context_t *pHddCtx, uint8_t op_chan)
847{
848 tHddAvoidFreqList p2p_avoid_freq_list;
849 uint8_t min_chan, max_chan;
850 int ret;
851 int chan;
852
853 ENTER();
854
855 if (!pHddCtx) {
856 hdd_err("invalid param");
857 return -EINVAL;
858 }
859
860 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(tHddAvoidFreqList));
861 /*
862 * If channel passed is zero, clear the avoid_freq list in application.
863 */
864 if (!op_chan) {
865 ret = wlan_hdd_send_avoid_freq_event(pHddCtx,
866 &p2p_avoid_freq_list);
867 if (ret)
868 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
869 ret);
870
871 return ret;
872 }
873
874 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
875 min_chan = REG_MIN_24GHZ_CH_NUM;
876 max_chan = REG_MAX_24GHZ_CH_NUM;
877 } else if WLAN_REG_IS_5GHZ_CH(op_chan) {
878 min_chan = REG_MIN_5GHZ_CH_NUM;
879 max_chan = REG_MAX_5GHZ_CH_NUM;
880 } else {
881 hdd_err("invalid channel:%d", op_chan);
882 return -EINVAL;
883 }
884
885 if ((op_chan > min_chan) && (op_chan < max_chan)) {
886 p2p_avoid_freq_list.avoidFreqRangeCount = 2;
887 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
888 wlan_chan_to_freq(min_chan);
889
890 /* Get channel before the op_chan */
891 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
892 if (chan < 0)
893 return -EINVAL;
894 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
895 wlan_chan_to_freq(chan);
896
897 /* Get channel next to the op_chan */
898 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
899 if (chan < 0)
900 return -EINVAL;
901 p2p_avoid_freq_list.avoidFreqRange[1].startFreq =
902 wlan_chan_to_freq(chan);
903
904 p2p_avoid_freq_list.avoidFreqRange[1].endFreq =
905 wlan_chan_to_freq(max_chan);
906 } else if (op_chan == min_chan) {
907 p2p_avoid_freq_list.avoidFreqRangeCount = 1;
908
909 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
910 if (chan < 0)
911 return -EINVAL;
912 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
913 wlan_chan_to_freq(chan);
914
915 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
916 wlan_chan_to_freq(max_chan);
917 } else {
918 p2p_avoid_freq_list.avoidFreqRangeCount = 1;
919 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
920 wlan_chan_to_freq(min_chan);
921
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
929 ret = wlan_hdd_send_avoid_freq_event(pHddCtx, &p2p_avoid_freq_list);
930 if (ret)
931 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
932
933 return ret;
934}
935
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800936/* vendor specific events */
937static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800938 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
939 .vendor_id =
940 QCA_NL80211_VENDOR_ID,
941 .subcmd =
942 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
943 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944
945#ifdef WLAN_FEATURE_NAN
946 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_NAN
951 },
952#endif
953
954#ifdef WLAN_FEATURE_STATS_EXT
955 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
956 .vendor_id =
957 QCA_NL80211_VENDOR_ID,
958 .subcmd =
959 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
960 },
961#endif /* WLAN_FEATURE_STATS_EXT */
962#ifdef FEATURE_WLAN_EXTSCAN
963 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
964 .vendor_id =
965 QCA_NL80211_VENDOR_ID,
966 .subcmd =
967 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
968 },
969 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
970 .vendor_id =
971 QCA_NL80211_VENDOR_ID,
972 .subcmd =
973 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
974 },
975 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
976 .
977 vendor_id
978 =
979 QCA_NL80211_VENDOR_ID,
980 .subcmd =
981 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
982 },
983 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
984 .
985 vendor_id
986 =
987 QCA_NL80211_VENDOR_ID,
988 .
989 subcmd =
990 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
991 },
992 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
993 .
994 vendor_id
995 =
996 QCA_NL80211_VENDOR_ID,
997 .
998 subcmd
999 =
1000 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1001 },
1002 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1003 .
1004 vendor_id
1005 =
1006 QCA_NL80211_VENDOR_ID,
1007 .subcmd =
1008 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1009 },
1010 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1011 .vendor_id =
1012 QCA_NL80211_VENDOR_ID,
1013 .subcmd =
1014 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1015 },
1016 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1017 .
1018 vendor_id
1019 =
1020 QCA_NL80211_VENDOR_ID,
1021 .subcmd =
1022 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1023 },
1024 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1025 .
1026 vendor_id
1027 =
1028 QCA_NL80211_VENDOR_ID,
1029 .subcmd =
1030 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1031 },
1032 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1033 .
1034 vendor_id
1035 =
1036 QCA_NL80211_VENDOR_ID,
1037 .
1038 subcmd
1039 =
1040 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1041 },
1042 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1043 .
1044 vendor_id
1045 =
1046 QCA_NL80211_VENDOR_ID,
1047 .
1048 subcmd =
1049 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1050 },
1051 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1052 .
1053 vendor_id
1054 =
1055 QCA_NL80211_VENDOR_ID,
1056 .
1057 subcmd
1058 =
1059 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1060 },
1061 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1062 .
1063 vendor_id
1064 =
1065 QCA_NL80211_VENDOR_ID,
1066 .
1067 subcmd
1068 =
1069 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1070 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071#endif /* FEATURE_WLAN_EXTSCAN */
1072
1073#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1074 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1075 .vendor_id =
1076 QCA_NL80211_VENDOR_ID,
1077 .subcmd =
1078 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1079 },
1080 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1081 .vendor_id =
1082 QCA_NL80211_VENDOR_ID,
1083 .subcmd =
1084 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1085 },
1086 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1087 .vendor_id =
1088 QCA_NL80211_VENDOR_ID,
1089 .subcmd =
1090 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1091 },
1092 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1093 .vendor_id =
1094 QCA_NL80211_VENDOR_ID,
1095 .subcmd =
1096 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1097 },
1098 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1099 .vendor_id =
1100 QCA_NL80211_VENDOR_ID,
1101 .subcmd =
1102 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1103 },
1104 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1105 .vendor_id =
1106 QCA_NL80211_VENDOR_ID,
1107 .subcmd =
1108 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1109 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001110 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1111 .vendor_id =
1112 QCA_NL80211_VENDOR_ID,
1113 .subcmd =
1114 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1115 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001116#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1117 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1118 .vendor_id =
1119 QCA_NL80211_VENDOR_ID,
1120 .subcmd =
1121 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1122 },
1123 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1124 .vendor_id = QCA_NL80211_VENDOR_ID,
1125 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1126 },
1127#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1128 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1129 .vendor_id =
1130 QCA_NL80211_VENDOR_ID,
1131 .subcmd =
1132 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1133 },
1134#endif
1135 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1136 .vendor_id =
1137 QCA_NL80211_VENDOR_ID,
1138 .subcmd =
1139 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1140 },
1141 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1142 .vendor_id =
1143 QCA_NL80211_VENDOR_ID,
1144 .subcmd =
1145 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1146 },
1147 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1148 .vendor_id =
1149 QCA_NL80211_VENDOR_ID,
1150 .subcmd =
1151 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1152 },
1153 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1154 .vendor_id =
1155 QCA_NL80211_VENDOR_ID,
1156 .subcmd =
1157 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1158 },
1159 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1160 .vendor_id =
1161 QCA_NL80211_VENDOR_ID,
1162 .subcmd =
1163 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1164 },
1165#ifdef FEATURE_WLAN_EXTSCAN
1166 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1167 .vendor_id = QCA_NL80211_VENDOR_ID,
1168 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1169 },
1170 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1171 .vendor_id = QCA_NL80211_VENDOR_ID,
1172 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1173 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001174 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1175 .vendor_id = QCA_NL80211_VENDOR_ID,
1176 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1177 },
1178#endif /* FEATURE_WLAN_EXTSCAN */
1179 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1180 .vendor_id = QCA_NL80211_VENDOR_ID,
1181 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1182 },
1183#ifdef WLAN_FEATURE_MEMDUMP
1184 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1185 .vendor_id = QCA_NL80211_VENDOR_ID,
1186 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1187 },
1188#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001189#ifdef WLAN_FEATURE_TSF
1190 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1191 .vendor_id = QCA_NL80211_VENDOR_ID,
1192 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1193 },
1194#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1196 .vendor_id = QCA_NL80211_VENDOR_ID,
1197 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1198 },
1199 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1200 .vendor_id = QCA_NL80211_VENDOR_ID,
1201 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1202 },
1203 /* OCB events */
1204 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1205 .vendor_id = QCA_NL80211_VENDOR_ID,
1206 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1207 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001208#ifdef FEATURE_LFR_SUBNET_DETECTION
1209 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1210 .vendor_id = QCA_NL80211_VENDOR_ID,
1211 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1212 },
1213#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001214
1215#ifdef WLAN_FEATURE_NAN_DATAPATH
1216 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1217 .vendor_id = QCA_NL80211_VENDOR_ID,
1218 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1219 },
1220#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001221
1222 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1223 .vendor_id = QCA_NL80211_VENDOR_ID,
1224 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1225 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301226 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1227 .vendor_id = QCA_NL80211_VENDOR_ID,
1228 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1229 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301230 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1231 .vendor_id = QCA_NL80211_VENDOR_ID,
1232 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1233 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001234#ifdef WLAN_UMAC_CONVERGENCE
1235 COMMON_VENDOR_EVENTS
1236#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237};
1238
1239/**
1240 * __is_driver_dfs_capable() - get driver DFS capability
1241 * @wiphy: pointer to wireless wiphy structure.
1242 * @wdev: pointer to wireless_dev structure.
1243 * @data: Pointer to the data to be passed via vendor interface
1244 * @data_len:Length of the data to be passed
1245 *
1246 * This function is called by userspace to indicate whether or not
1247 * the driver supports DFS offload.
1248 *
1249 * Return: 0 on success, negative errno on failure
1250 */
1251static int __is_driver_dfs_capable(struct wiphy *wiphy,
1252 struct wireless_dev *wdev,
1253 const void *data,
1254 int data_len)
1255{
1256 u32 dfs_capability = 0;
1257 struct sk_buff *temp_skbuff;
1258 int ret_val;
1259 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1260
Jeff Johnson1f61b612016-02-12 16:28:33 -08001261 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001262
1263 ret_val = wlan_hdd_validate_context(hdd_ctx);
1264 if (ret_val)
1265 return ret_val;
1266
Anurag Chouhan6d760662016-02-20 16:05:43 +05301267 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001268 hdd_err("Command not allowed in FTM mode");
1269 return -EPERM;
1270 }
1271
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001273
1274 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1275 NLMSG_HDRLEN);
1276
1277 if (temp_skbuff != NULL) {
1278 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1279 dfs_capability);
1280 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001281 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282 kfree_skb(temp_skbuff);
1283
1284 return ret_val;
1285 }
1286
1287 return cfg80211_vendor_cmd_reply(temp_skbuff);
1288 }
1289
Jeff Johnson020db452016-06-29 14:37:26 -07001290 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 return -ENOMEM;
1292}
1293
1294/**
1295 * is_driver_dfs_capable() - get driver DFS capability
1296 * @wiphy: pointer to wireless wiphy structure.
1297 * @wdev: pointer to wireless_dev structure.
1298 * @data: Pointer to the data to be passed via vendor interface
1299 * @data_len:Length of the data to be passed
1300 *
1301 * This function is called by userspace to indicate whether or not
1302 * the driver supports DFS offload. This is an SSR-protected
1303 * wrapper function.
1304 *
1305 * Return: 0 on success, negative errno on failure
1306 */
1307static int is_driver_dfs_capable(struct wiphy *wiphy,
1308 struct wireless_dev *wdev,
1309 const void *data,
1310 int data_len)
1311{
1312 int ret;
1313
1314 cds_ssr_protect(__func__);
1315 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1316 cds_ssr_unprotect(__func__);
1317
1318 return ret;
1319}
1320
1321/**
1322 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1323 *
1324 * @adapter: SAP adapter pointer
1325 *
1326 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1327 * radio. So in case of DFS MCC scenario override current SAP given config
1328 * to follow concurrent SAP DFS config
1329 *
1330 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1331 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001332int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1333{
1334 hdd_adapter_t *con_sap_adapter;
1335 tsap_Config_t *sap_config, *con_sap_config;
1336 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001337 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001338
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001339 if (!hdd_ctx) {
1340 hdd_err("hdd context is NULL");
1341 return 0;
1342 }
1343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344 /*
1345 * Check if AP+AP case, once primary AP chooses a DFS
1346 * channel secondary AP should always follow primary APs channel
1347 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001348 if (!policy_mgr_concurrent_beaconing_sessions_running(
1349 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001350 return 0;
1351
1352 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1353 if (!con_sap_adapter)
1354 return 0;
1355
1356 sap_config = &adapter->sessionCtx.ap.sapConfig;
1357 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1358 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1359
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001360 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361 return 0;
1362
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001363 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001365 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001366 sap_config->channel = con_ch;
1367
1368 if (con_sap_config->acs_cfg.acs_mode == true) {
1369 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1370 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001371 hdd_err("Primary AP channel config error");
1372 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 con_ch, con_sap_config->acs_cfg.pri_ch,
1374 con_sap_config->acs_cfg.ht_sec_ch);
1375 return -EINVAL;
1376 }
1377 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1378 * MCC restriction. So free ch list allocated in do_acs
1379 * func for Sec AP and realloc for Pri AP ch list size
1380 */
1381 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301382 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301384 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 &con_sap_config->acs_cfg,
1386 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301387 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 sizeof(uint8_t) *
1389 con_sap_config->acs_cfg.ch_list_count);
1390 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001391 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 return -ENOMEM;
1393 }
1394
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301395 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001396 con_sap_config->acs_cfg.ch_list,
1397 con_sap_config->acs_cfg.ch_list_count);
1398
1399 } else {
1400 sap_config->acs_cfg.pri_ch = con_ch;
1401 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1402 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1403 }
1404
1405 return con_ch;
1406}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001407
1408/**
1409 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1410 * @sap_cfg: pointer to SAP config struct
1411 *
1412 * This function sets the default ACS start and end channel for the given band
1413 * and also parses the given ACS channel list.
1414 *
1415 * Return: None
1416 */
1417
1418static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1419 bool vht_enabled)
1420{
1421 int i;
1422 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1423 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001424 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1425 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001426 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1427 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001428 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1429 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001430 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1431 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001432 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1433 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1435 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001436 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1437 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001438 }
1439
1440 if (ht_enabled)
1441 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1442
1443 if (vht_enabled)
1444 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1445
1446
1447 /* Parse ACS Chan list from hostapd */
1448 if (!sap_cfg->acs_cfg.ch_list)
1449 return;
1450
1451 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1452 sap_cfg->acs_cfg.end_ch =
1453 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1454 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301455 /* avoid channel as start channel */
1456 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1457 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001458 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1459 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1460 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1461 }
1462}
1463
1464
1465static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1466
1467/**
1468 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1469 * @adapter: pointer to SAP adapter struct
1470 *
1471 * This function starts the ACS procedure if there are no
1472 * constraints like MBSSID DFS restrictions.
1473 *
1474 * Return: Status of ACS Start procedure
1475 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301476int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477{
1478
1479 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1480 tsap_Config_t *sap_config;
1481 tpWLAN_SAPEventCB acs_event_callback;
1482 int status;
1483
1484 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301485 if (hdd_ctx->acs_policy.acs_channel)
1486 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1487 else
1488 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489
1490 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001491 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001493
1494 if (status > 0) {
1495 /*notify hostapd about channel override */
1496 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1497 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1498 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001499 }
Jeff Johnson68755312017-02-10 11:46:55 -08001500
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001501 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1502 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001503 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001504 return -EINVAL;
1505 }
1506
1507 acs_event_callback = hdd_hostapd_sap_event_cb;
1508
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301509 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301510 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301511 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001512 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001513 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001514 acs_event_callback, sap_config, adapter->dev);
1515
1516
1517 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001518 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519 return -EINVAL;
1520 }
bings394afdd2017-01-09 11:22:38 +08001521 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1522 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1524
1525 return 0;
1526}
1527
1528/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301529 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1530 * @ap_adapter: AP adapter
1531 * @nol: Non-occupancy list
1532 * @nol_len: Length of NOL
1533 *
1534 * Get the NOL for SAP
1535 *
1536 * Return: Zero on success, non-zero on failure
1537 */
1538static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1539 uint32_t *nol_len)
1540{
1541 QDF_STATUS ret;
1542
1543 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1544 nol, nol_len);
1545 if (QDF_IS_STATUS_ERROR(ret))
1546 return -EINVAL;
1547
1548 return 0;
1549}
1550
1551/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301552 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1553 * @hdd_ctx: hdd context
1554 * @acs_chan_params: external acs channel params
1555 * @sap_config: SAP config
1556 *
1557 * This API provides unsorted pcl list.
1558 * this list is a subset of the valid channel list given by hostapd.
1559 * if channel is not present in pcl, weightage will be given as zero
1560 *
1561 * Return: Zero on success, non-zero on failure
1562 */
1563static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1564 struct hdd_vendor_acs_chan_params *acs_chan_params,
1565 tsap_Config_t *sap_config)
1566{
1567 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301568 /*
1569 * PCL shall contain only the preferred channels from the
1570 * application. If those channels are not present in the
1571 * driver PCL, then set the weight to zero
1572 */
1573 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1574 acs_chan_params->vendor_pcl_list[i] =
1575 sap_config->acs_cfg.ch_list[i];
1576 acs_chan_params->vendor_weight_list[i] = 0;
1577 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1578 if (sap_config->acs_cfg.ch_list[i] ==
1579 sap_config->acs_cfg.pcl_channels[j]) {
1580 acs_chan_params->vendor_weight_list[i] =
1581 sap_config->
1582 acs_cfg.pcl_channels_weight_list[j];
1583 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301584 }
1585 }
1586 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301587 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301588}
1589
1590/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301591 * hdd_update_reg_chan_info : This API contructs channel info
1592 * for all the given channel
1593 * @adapter: pointer to SAP adapter struct
1594 * @channel_count: channel count
1595 * @channel_list: channel list
1596 *
1597 * Return: Status of of channel information updation
1598 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301599static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301600 uint32_t channel_count,
1601 uint8_t *channel_list)
1602{
1603 int i;
1604 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001605 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301606 uint8_t bw_offset = 0, chan = 0;
1607 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1608 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1609
1610 /* memory allocation */
1611 sap_config->channel_info = qdf_mem_malloc(
1612 sizeof(struct hdd_channel_info) *
1613 channel_count);
1614 if (!sap_config->channel_info) {
1615 hdd_err("memory allocation failed");
1616 return -ENOMEM;
1617
1618 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301619 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301620 for (i = 0; i < channel_count; i++) {
1621 icv = &sap_config->channel_info[i];
1622 chan = channel_list[i];
1623
1624 if (chan == 0)
1625 continue;
1626
1627 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1628 bw_offset = 1 << BW_40_OFFSET_BIT;
1629 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1630 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001631 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301632 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001633 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1634 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301635
1636 /* filling demo values */
1637 icv->max_radio_power = HDD_MAX_TX_POWER;
1638 icv->min_radio_power = HDD_MIN_TX_POWER;
1639 /* not supported in current driver */
1640 icv->max_antenna_gain = 0;
1641
1642 icv->reg_class_id = wlan_hdd_find_opclass(
1643 WLAN_HDD_GET_HAL_CTX(adapter),
1644 chan, bw_offset);
1645
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001646 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301647 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001648 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1649 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301650 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1651 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1652 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001653
Kapil Gupta086c6202016-12-11 18:17:06 +05301654 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001655 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301656 sap_config->acs_cfg.ch_width,
1657 sap_config->acs_cfg.is_ht_enabled,
1658 sap_config->acs_cfg.is_vht_enabled,
1659 hdd_ctx->config->enable_sub_20_channel_width);
1660
1661 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1662 icv->freq, icv->flags,
1663 icv->flagext, icv->ieee_chan_number,
1664 icv->max_reg_power, icv->max_radio_power,
1665 icv->min_radio_power, icv->reg_class_id,
1666 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1667 icv->vht_center_freq_seg1);
1668 }
1669 return 0;
1670}
1671
1672/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1673#define CHAN_INFO_ATTR_FLAGS \
1674 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1675#define CHAN_INFO_ATTR_FLAG_EXT \
1676 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1677#define CHAN_INFO_ATTR_FREQ \
1678 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1679#define CHAN_INFO_ATTR_MAX_REG_POWER \
1680 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1681#define CHAN_INFO_ATTR_MAX_POWER \
1682 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1683#define CHAN_INFO_ATTR_MIN_POWER \
1684 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1685#define CHAN_INFO_ATTR_REG_CLASS_ID \
1686 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1687#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1688 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1689#define CHAN_INFO_ATTR_VHT_SEG_0 \
1690 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1691#define CHAN_INFO_ATTR_VHT_SEG_1 \
1692 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1693
1694/**
1695 * hdd_cfg80211_update_channel_info() - add channel info attributes
1696 * @skb: pointer to sk buff
1697 * @hdd_ctx: pointer to hdd station context
1698 * @idx: attribute index
1699 *
1700 * Return: Success(0) or reason code for failure
1701 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301702static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301703hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1704 tsap_Config_t *sap_config, int idx)
1705{
1706 struct nlattr *nla_attr, *channel;
1707 struct hdd_channel_info *icv;
1708 int i;
1709
1710 nla_attr = nla_nest_start(skb, idx);
1711 if (!nla_attr)
1712 goto fail;
1713
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301714 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301715 channel = nla_nest_start(skb, i);
1716 if (!channel)
1717 goto fail;
1718
1719 icv = &sap_config->channel_info[i];
1720 if (!icv) {
1721 hdd_err("channel info not found");
1722 goto fail;
1723 }
1724 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1725 icv->freq) ||
1726 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1727 icv->flags) ||
1728 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1729 icv->flagext) ||
1730 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1731 icv->max_reg_power) ||
1732 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1733 icv->max_radio_power) ||
1734 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1735 icv->min_radio_power) ||
1736 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1737 icv->reg_class_id) ||
1738 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1739 icv->max_antenna_gain) ||
1740 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1741 icv->vht_center_freq_seg0) ||
1742 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1743 icv->vht_center_freq_seg1)) {
1744 hdd_err("put fail");
1745 goto fail;
1746 }
1747 nla_nest_end(skb, channel);
1748 }
1749 nla_nest_end(skb, nla_attr);
1750 return 0;
1751fail:
1752 hdd_err("nl channel update failed");
1753 return -EINVAL;
1754}
1755#undef CHAN_INFO_ATTR_FLAGS
1756#undef CHAN_INFO_ATTR_FLAG_EXT
1757#undef CHAN_INFO_ATTR_FREQ
1758#undef CHAN_INFO_ATTR_MAX_REG_POWER
1759#undef CHAN_INFO_ATTR_MAX_POWER
1760#undef CHAN_INFO_ATTR_MIN_POWER
1761#undef CHAN_INFO_ATTR_REG_CLASS_ID
1762#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1763#undef CHAN_INFO_ATTR_VHT_SEG_0
1764#undef CHAN_INFO_ATTR_VHT_SEG_1
1765
1766/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301767 * hdd_cfg80211_update_pcl() - add pcl info attributes
1768 * @skb: pointer to sk buff
1769 * @hdd_ctx: pointer to hdd station context
1770 * @idx: attribute index
1771 * @vendor_pcl_list: PCL list
1772 * @vendor_weight_list: PCL weights
1773 *
1774 * Return: Success(0) or reason code for failure
1775 */
1776static int32_t
1777hdd_cfg80211_update_pcl(struct sk_buff *skb,
1778 uint8_t ch_list_count, int idx,
1779 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1780{
1781 struct nlattr *nla_attr, *channel;
1782 int i;
1783
1784 nla_attr = nla_nest_start(skb, idx);
1785
1786 if (!nla_attr)
1787 goto fail;
1788
1789 for (i = 0; i < ch_list_count; i++) {
1790 channel = nla_nest_start(skb, i);
1791 if (!channel)
1792 goto fail;
1793 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1794 vendor_pcl_list[i]) ||
1795 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1796 vendor_weight_list[i])) {
1797 hdd_err("put fail");
1798 goto fail;
1799 }
1800 nla_nest_end(skb, channel);
1801 }
1802 nla_nest_end(skb, nla_attr);
1803
1804 return 0;
1805fail:
1806 hdd_err("updating pcl list failed");
1807 return -EINVAL;
1808}
1809
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301810static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
1811 tsap_Config_t *sap_config,
1812 eCsrBand *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301813{
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301814 int i, temp_count = 0;
1815 int acs_list_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301816 /* Get scan band */
1817 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1818 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1819 *band = eCSR_BAND_24;
1820 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1821 *band = eCSR_BAND_5G;
1822 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1823 *band = eCSR_BAND_ALL;
1824 }
1825 /* Auto is not supported currently */
1826 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1827 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301828 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
1829 hdd_ctx->config->external_acs_freq_band)
1830 *band = eCSR_BAND_24;
1831 else
1832 *band = eCSR_BAND_5G;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301833 for (i = 0; i < acs_list_count; i++) {
1834 if (eCSR_BAND_24 == *band) {
1835 if (WLAN_REG_IS_24GHZ_CH(
1836 sap_config->acs_cfg.ch_list[i])) {
1837 sap_config->acs_cfg.ch_list[
1838 temp_count] =
1839 sap_config->acs_cfg.ch_list[i];
1840 temp_count++;
1841 }
1842 } else if (eCSR_BAND_5G == *band) {
1843 if (WLAN_REG_IS_5GHZ_CH(
1844 sap_config->acs_cfg.ch_list[i])) {
1845 sap_config->acs_cfg.ch_list[
1846 temp_count] =
1847 sap_config->acs_cfg.ch_list[i];
1848 temp_count++;
1849 }
1850 }
1851 }
1852 sap_config->acs_cfg.ch_list_count = temp_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301853 }
1854}
1855
1856void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1857 uint8_t reason)
1858{
1859 struct sk_buff *skb;
1860 tsap_Config_t *sap_config;
1861 uint32_t channel_count = 0, status;
1862 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1863 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1864 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1865 struct hdd_vendor_acs_chan_params acs_chan_params;
1866 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1867 eCsrBand band = eCSR_BAND_24;
1868 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301869 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
1870 uint32_t i;
1871
Kapil Gupta8878ad92017-02-13 11:56:04 +05301872
1873 if (!hdd_ctx) {
1874 hdd_err("HDD context is NULL");
1875 return;
1876 }
1877
1878 ENTER();
1879 sap_config = &adapter->sessionCtx.ap.sapConfig;
1880
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301881 hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301882 /* Get valid channels for SAP */
1883 wlan_hdd_sap_get_valid_channellist(adapter,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301884 &channel_count,
1885 channel_list,
1886 band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301887
1888 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301889 /* Get phymode */
1890 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1891
1892 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1893 &(adapter->wdev),
1894 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1895 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1896 GFP_KERNEL);
1897
1898 if (!skb) {
1899 hdd_err("cfg80211_vendor_event_alloc failed");
1900 return;
1901 }
1902 /*
1903 * Application expects pcl to be a subset of channel list
1904 * Remove all channels which are not in channel list from pcl
1905 * and add weight as zero
1906 */
1907 acs_chan_params.channel_count = channel_count;
1908 acs_chan_params.channel_list = channel_list;
1909 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1910 acs_chan_params.vendor_weight_list = vendor_weight_list;
1911
1912 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1913 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301914
1915 if (acs_chan_params.channel_count) {
1916 hdd_debug("ACS channel list: len: %d",
1917 acs_chan_params.channel_count);
1918 for (i = 0; i < acs_chan_params.channel_count; i++)
1919 hdd_debug("%d ", acs_chan_params.channel_list[i]);
1920 }
1921
1922 if (acs_chan_params.pcl_count) {
1923 hdd_debug("ACS PCL list: len: %d",
1924 acs_chan_params.pcl_count);
1925 for (i = 0; i < acs_chan_params.pcl_count; i++)
1926 hdd_debug("channel:%d, weight:%d ",
1927 acs_chan_params.
1928 vendor_pcl_list[i],
1929 acs_chan_params.
1930 vendor_weight_list[i]);
1931 }
1932
1933 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1934 hdd_ctx->config->external_acs_policy) {
1935 acs_policy =
1936 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
1937 } else {
1938 acs_policy =
1939 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
1940 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301941 /* Update values in NL buffer */
1942 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1943 reason) ||
1944 nla_put_u8(skb,
1945 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1946 false) ||
1947 nla_put_u8(skb,
1948 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1949 true) ||
1950 nla_put_u8(skb,
1951 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1952 true) ||
1953 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1954 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05301955 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1956 band) ||
1957 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1958 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05301959 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301960 channel_count, channel_list)) {
1961 hdd_err("nla put fail");
1962 goto fail;
1963 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301964 status =
1965 hdd_cfg80211_update_pcl(skb,
1966 acs_chan_params.
1967 pcl_count,
1968 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1969 vendor_pcl_list,
1970 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301971
1972 if (status != 0)
1973 goto fail;
1974
1975 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1976 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1977
1978 if (status != 0)
1979 goto fail;
1980
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301981 status = nla_put_u32(skb,
1982 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
1983 acs_policy);
1984
1985 if (status != 0)
1986 goto fail;
1987
Kapil Gupta8878ad92017-02-13 11:56:04 +05301988 cfg80211_vendor_event(skb, GFP_KERNEL);
1989 return;
1990fail:
1991 if (skb)
1992 kfree_skb(skb);
1993}
1994
1995static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1996{
1997 struct hdd_external_acs_timer_context *timer_context;
1998
1999 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
2000 return 0;
2001
2002 hdd_notice("Starting vendor app based ACS");
2003 timer_context = qdf_mem_malloc(sizeof(*timer_context));
2004 timer_context->adapter = adapter;
2005
2006 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
2007 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
2008 QDF_TIMER_TYPE_SW,
2009 hdd_acs_response_timeout_handler, timer_context);
2010 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
2011 return 0;
2012}
2013
2014/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002015 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2016 * @wiphy: Linux wiphy struct pointer
2017 * @wdev: Linux wireless device struct pointer
2018 * @data: ACS information from hostapd
2019 * @data_len: ACS information length
2020 *
2021 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2022 * and starts ACS procedure.
2023 *
2024 * Return: ACS procedure start status
2025 */
2026
2027static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2028 struct wireless_dev *wdev,
2029 const void *data, int data_len)
2030{
2031 struct net_device *ndev = wdev->netdev;
2032 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
2033 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2034 tsap_Config_t *sap_config;
2035 struct sk_buff *temp_skbuff;
2036 int status = -EINVAL, i = 0;
2037 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2038 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302039 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040
2041 /* ***Note*** Donot set SME config related to ACS operation here because
2042 * ACS operation is not synchronouse and ACS for Second AP may come when
2043 * ACS operation for first AP is going on. So only do_acs is split to
2044 * seperate start_acs routine. Also SME-PMAC struct that is used to
2045 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2046 * config shall be set only from start_acs.
2047 */
2048
2049 /* nla_policy Policy template. Policy not applied as some attributes are
2050 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
2051 *
2052 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2053 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2054 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2055 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2056 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2057 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
2058 */
2059
Jeff Johnson1f61b612016-02-12 16:28:33 -08002060 ENTER_DEV(ndev);
2061
Anurag Chouhan6d760662016-02-20 16:05:43 +05302062 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063 hdd_err("Command not allowed in FTM mode");
2064 return -EPERM;
2065 }
2066
Kapil Gupta8878ad92017-02-13 11:56:04 +05302067 if (hdd_ctx->config->force_sap_acs &&
2068 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07002069 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002070 return -EPERM;
2071 }
2072
2073 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302074 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302076
Naveen Rawat64e477e2016-05-20 10:34:56 -07002077 if (cds_is_sub_20_mhz_enabled()) {
2078 hdd_err("ACS not supported in sub 20 MHz ch wd.");
2079 status = -EINVAL;
2080 goto out;
2081 }
2082
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002083 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302084 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085
2086 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
2087 NULL);
2088 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07002089 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002090 goto out;
2091 }
2092
2093 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002094 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002095 goto out;
2096 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302097 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
2098 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002099
2100 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2101 ht_enabled =
2102 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2103 else
2104 ht_enabled = 0;
2105
2106 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2107 ht40_enabled =
2108 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2109 else
2110 ht40_enabled = 0;
2111
2112 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2113 vht_enabled =
2114 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2115 else
2116 vht_enabled = 0;
2117
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302118 if (hdd_ctx->config->sap_force_11n_for_11ac) {
2119 vht_enabled = 0;
2120 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
2121 }
2122
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002123 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2124 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2125 } else {
2126 if (ht_enabled && ht40_enabled)
2127 ch_width = 40;
2128 else
2129 ch_width = 20;
2130 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302131
2132 /* this may be possible, when sap_force_11n_for_11ac is set */
2133 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2134 if (ht_enabled && ht40_enabled)
2135 ch_width = 40;
2136 else
2137 ch_width = 20;
2138 }
2139
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002140 if (ch_width == 80)
2141 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2142 else if (ch_width == 40)
2143 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2144 else
2145 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2146
2147 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2148 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2149 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2150 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2151 * since it contains the frequency values of the channels in
2152 * the channel list.
2153 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2154 * is present
2155 */
2156 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2157 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2158 sap_config->acs_cfg.ch_list_count = nla_len(
2159 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2160 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302161 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162 sizeof(uint8_t) *
2163 sap_config->acs_cfg.ch_list_count);
2164 if (sap_config->acs_cfg.ch_list == NULL)
2165 goto out;
2166
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302167 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002168 sap_config->acs_cfg.ch_list_count);
2169 }
2170 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2171 uint32_t *freq =
2172 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2173 sap_config->acs_cfg.ch_list_count = nla_len(
2174 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2175 sizeof(uint32_t);
2176 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302177 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178 sap_config->acs_cfg.ch_list_count);
2179 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07002180 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002181 status = -ENOMEM;
2182 goto out;
2183 }
2184
2185 /* convert frequency to channel */
2186 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2187 sap_config->acs_cfg.ch_list[i] =
2188 ieee80211_frequency_to_channel(freq[i]);
2189 }
2190 }
2191
2192 hdd_debug("get pcl for DO_ACS vendor command");
2193
2194 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002195 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302196 sap_config->acs_cfg.pcl_channels,
2197 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302198 sap_config->acs_cfg.pcl_channels_weight_list,
2199 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302200 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002201 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302203 if (sap_config->acs_cfg.pcl_ch_count) {
2204 hdd_debug("ACS config PCL: len: %d",
2205 sap_config->acs_cfg.pcl_ch_count);
2206 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2207 hdd_debug("channel:%d, weight:%d ",
2208 sap_config->acs_cfg.
2209 pcl_channels[i],
2210 sap_config->acs_cfg.
2211 pcl_channels_weight_list[i]);
2212 }
2213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002214 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302215 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2216 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002217 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218 vht_enabled = 1;
2219 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2220 sap_config->acs_cfg.ch_width =
2221 hdd_ctx->config->vhtChannelWidth;
2222 /* No VHT80 in 2.4G so perform ACS accordingly */
2223 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302224 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302226 ch_width = 40;
2227 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002228 }
2229
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302230 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2231
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002232 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 -08002233 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2234 ch_width, ht_enabled, vht_enabled,
2235 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2236
Kapil Gupta8878ad92017-02-13 11:56:04 +05302237 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2238 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2239
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002240 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002241 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002242 sap_config->acs_cfg.ch_list_count);
2243 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002244 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002245 }
2246 sap_config->acs_cfg.acs_mode = true;
2247 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002248 /* ***Note*** Completion variable usage is not allowed
2249 * here since ACS scan operation may take max 2.2 sec
2250 * for 5G band:
2251 * 9 Active channel X 40 ms active scan time +
2252 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002253 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2254 * for this long. So we split up the scanning part.
2255 */
2256 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002257 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002258 status = 0;
2259 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302260 /* Check if vendor specific acs is enabled */
2261 if (hdd_ctx->config->vendor_acs_support) {
2262 sap_config->acs_cfg.hw_mode = hw_mode;
2263 hdd_create_acs_timer(adapter);
2264 hdd_update_acs_timer_reason(adapter,
2265 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2266 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2267 wlan_sap_set_vendor_acs(
2268 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2269 true);
2270 else
2271 wlan_sap_set_vendor_acs(
2272 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2273 false);
2274
2275 } else
2276 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002277 }
2278
2279out:
2280 if (0 == status) {
2281 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2282 NLMSG_HDRLEN);
2283 if (temp_skbuff != NULL)
2284 return cfg80211_vendor_cmd_reply(temp_skbuff);
2285 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002286 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002287 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2288
2289 return status;
2290}
2291
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002292/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002293 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2294 * @wiphy: Linux wiphy struct pointer
2295 * @wdev: Linux wireless device struct pointer
2296 * @data: ACS information from hostapd
2297 * @data_len: ACS information len
2298 *
2299 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2300 * and starts ACS procedure.
2301 *
2302 * Return: ACS procedure start status
2303 */
2304
2305static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2306 struct wireless_dev *wdev,
2307 const void *data, int data_len)
2308{
2309 int ret;
2310
2311 cds_ssr_protect(__func__);
2312 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2313 cds_ssr_unprotect(__func__);
2314
2315 return ret;
2316}
2317
2318/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002319 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2320 * @adapter: Pointer to adapter struct
2321 *
2322 * This function handle cleanup of what was done in DO_ACS, including free
2323 * memory.
2324 *
2325 * Return: void
2326 */
2327
2328void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2329{
2330 if (adapter == NULL)
2331 return;
2332 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2333 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2334 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2335 }
2336}
2337
2338/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002339 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2340 * @work: Linux workqueue struct pointer for ACS work
2341 *
2342 * This function starts the ACS procedure which was marked pending when an ACS
2343 * procedure was in progress for a concurrent SAP interface.
2344 *
2345 * Return: None
2346 */
2347
2348static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2349{
2350 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2351 acs_pending_work.work);
2352 wlan_hdd_cfg80211_start_acs(adapter);
2353}
2354
2355/**
2356 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2357 * @adapter: Pointer to SAP adapter struct
2358 * @pri_channel: SAP ACS procedure selected Primary channel
2359 * @sec_channel: SAP ACS procedure selected secondary channel
2360 *
2361 * This is a callback function from SAP module on ACS procedure is completed.
2362 * This function send the ACS selected channel information to hostapd
2363 *
2364 * Return: None
2365 */
2366
2367void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2368{
2369 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2370 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2371 struct sk_buff *vendor_event;
2372 int ret_val;
2373 hdd_adapter_t *con_sap_adapter;
2374 uint16_t ch_width;
2375
2376 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002377 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2379 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2380 GFP_KERNEL);
2381
2382 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002383 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 return;
2385 }
2386
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387 ret_val = nla_put_u8(vendor_event,
2388 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2389 sap_cfg->acs_cfg.pri_ch);
2390 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002391 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002392 kfree_skb(vendor_event);
2393 return;
2394 }
2395
2396 ret_val = nla_put_u8(vendor_event,
2397 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2398 sap_cfg->acs_cfg.ht_sec_ch);
2399 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002400 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401 kfree_skb(vendor_event);
2402 return;
2403 }
2404
2405 ret_val = nla_put_u8(vendor_event,
2406 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2407 sap_cfg->acs_cfg.vht_seg0_center_ch);
2408 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002409 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002410 kfree_skb(vendor_event);
2411 return;
2412 }
2413
2414 ret_val = nla_put_u8(vendor_event,
2415 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2416 sap_cfg->acs_cfg.vht_seg1_center_ch);
2417 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002418 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002419 kfree_skb(vendor_event);
2420 return;
2421 }
2422
2423 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2424 ch_width = 80;
2425 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2426 ch_width = 40;
2427 else
2428 ch_width = 20;
2429
2430 ret_val = nla_put_u16(vendor_event,
2431 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2432 ch_width);
2433 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002434 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 kfree_skb(vendor_event);
2436 return;
2437 }
2438 if (sap_cfg->acs_cfg.pri_ch > 14)
2439 ret_val = nla_put_u8(vendor_event,
2440 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2441 QCA_ACS_MODE_IEEE80211A);
2442 else
2443 ret_val = nla_put_u8(vendor_event,
2444 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2445 QCA_ACS_MODE_IEEE80211G);
2446
2447 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002448 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 kfree_skb(vendor_event);
2450 return;
2451 }
2452
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002453 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 -08002454 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2455 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2456 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2457
2458 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2459 /* ***Note*** As already mentioned Completion variable usage is not
2460 * allowed here since ACS scan operation may take max 2.2 sec.
2461 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2462 * operation.
2463 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2464 * when Primary AP ACS is complete and secondary AP ACS is started here
2465 * immediately, Primary AP start_bss may come inbetween ACS operation
2466 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2467 * delay. This path and below constraint will be removed on sessionizing
2468 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2469 * As per design constraint user space control application must take
2470 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2471 * this code path. Sec AP hostapd should be started after Primary AP
2472 * start beaconing which can be confirmed by getchannel iwpriv command
2473 */
2474
2475 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2476 if (con_sap_adapter &&
2477 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2479 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002480 /* Lets give 500ms for OBSS + START_BSS to complete */
2481 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2482 msecs_to_jiffies(500));
2483 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2484 }
2485
2486 return;
2487}
2488
2489static int
2490__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2491 struct wireless_dev *wdev,
2492 const void *data,
2493 int data_len)
2494{
2495 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2496 struct sk_buff *skb = NULL;
2497 uint32_t fset = 0;
2498 int ret;
2499
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002500 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302501
Anurag Chouhan6d760662016-02-20 16:05:43 +05302502 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503 hdd_err("Command not allowed in FTM mode");
2504 return -EPERM;
2505 }
2506
2507 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302508 if (ret)
2509 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002510
2511 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002512 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002513 fset |= WIFI_FEATURE_INFRA;
2514 }
2515 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002516 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 fset |= WIFI_FEATURE_INFRA_5G;
2518 }
2519#ifdef WLAN_FEATURE_P2P
2520 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2521 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002522 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002523 fset |= WIFI_FEATURE_P2P;
2524 }
2525#endif
2526 fset |= WIFI_FEATURE_SOFT_AP;
2527
2528 /* HOTSPOT is a supplicant feature, enable it by default */
2529 fset |= WIFI_FEATURE_HOTSPOT;
2530
2531#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302532 if (pHddCtx->config->extscan_enabled &&
2533 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002534 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2536 }
2537#endif
2538 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002539 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002540 fset |= WIFI_FEATURE_NAN;
2541 }
2542 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002543 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 fset |= WIFI_FEATURE_D2D_RTT;
2545 fset |= WIFI_FEATURE_D2AP_RTT;
2546 }
2547#ifdef FEATURE_WLAN_SCAN_PNO
2548 if (pHddCtx->config->configPNOScanSupport &&
2549 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002550 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551 fset |= WIFI_FEATURE_PNO;
2552 }
2553#endif
2554 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2555#ifdef FEATURE_WLAN_TDLS
2556 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2557 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002558 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559 fset |= WIFI_FEATURE_TDLS;
2560 }
2561 if (sme_is_feature_supported_by_fw(TDLS) &&
2562 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2563 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002564 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002565 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2566 }
2567#endif
2568#ifdef WLAN_AP_STA_CONCURRENCY
2569 fset |= WIFI_FEATURE_AP_STA;
2570#endif
2571 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002572 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002573
2574 if (hdd_link_layer_stats_supported())
2575 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2576
2577 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2578 NLMSG_HDRLEN);
2579 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002580 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 return -EINVAL;
2582 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002583 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002585 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002586 goto nla_put_failure;
2587 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302588 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302589 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002590nla_put_failure:
2591 kfree_skb(skb);
2592 return -EINVAL;
2593}
2594
2595/**
2596 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2597 * @wiphy: pointer to wireless wiphy structure.
2598 * @wdev: pointer to wireless_dev structure.
2599 * @data: Pointer to the data to be passed via vendor interface
2600 * @data_len:Length of the data to be passed
2601 *
2602 * Return: Return the Success or Failure code.
2603 */
2604static int
2605wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2606 struct wireless_dev *wdev,
2607 const void *data, int data_len)
2608{
2609 int ret = 0;
2610
2611 cds_ssr_protect(__func__);
2612 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2613 data, data_len);
2614 cds_ssr_unprotect(__func__);
2615
2616 return ret;
2617}
2618
2619/**
2620 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2621 * @wiphy: pointer to wireless wiphy structure.
2622 * @wdev: pointer to wireless_dev structure.
2623 * @data: Pointer to the data to be passed via vendor interface
2624 * @data_len:Length of the data to be passed
2625 *
2626 * Set the MAC address that is to be used for scanning.
2627 *
2628 * Return: Return the Success or Failure code.
2629 */
2630static int
2631__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2632 struct wireless_dev *wdev,
2633 const void *data,
2634 int data_len)
2635{
2636 tpSirScanMacOui pReqMsg = NULL;
2637 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2638 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302639 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002640 int ret;
2641
Jeff Johnson1f61b612016-02-12 16:28:33 -08002642 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002643
Anurag Chouhan6d760662016-02-20 16:05:43 +05302644 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002645 hdd_err("Command not allowed in FTM mode");
2646 return -EPERM;
2647 }
2648
2649 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302650 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002651 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002652
2653 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002654 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002655 return -ENOTSUPP;
2656 }
2657
2658 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2659 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002660 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002661 return -EINVAL;
2662 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302663 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002664 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002665 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002666 return -ENOMEM;
2667 }
2668 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002669 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 goto fail;
2671 }
2672 nla_memcpy(&pReqMsg->oui[0],
2673 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2674 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002675 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 pReqMsg->oui[1], pReqMsg->oui[2]);
2677 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302678 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002679 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 goto fail;
2681 }
2682 return 0;
2683fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302684 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685 return -EINVAL;
2686}
2687
2688/**
2689 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2690 * @wiphy: pointer to wireless wiphy structure.
2691 * @wdev: pointer to wireless_dev structure.
2692 * @data: Pointer to the data to be passed via vendor interface
2693 * @data_len:Length of the data to be passed
2694 *
2695 * Set the MAC address that is to be used for scanning. This is an
2696 * SSR-protecting wrapper function.
2697 *
2698 * Return: Return the Success or Failure code.
2699 */
2700static int
2701wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2702 struct wireless_dev *wdev,
2703 const void *data,
2704 int data_len)
2705{
2706 int ret;
2707
2708 cds_ssr_protect(__func__);
2709 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2710 data, data_len);
2711 cds_ssr_unprotect(__func__);
2712
2713 return ret;
2714}
2715
2716/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302717 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2718 * @wiphy: pointer phy adapter
2719 * @wdev: pointer to wireless device structure
2720 * @data: pointer to data buffer
2721 * @data_len: length of data
2722 *
2723 * This routine will give concurrency matrix
2724 *
2725 * Return: int status code
2726 */
2727static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2728 struct wireless_dev *wdev,
2729 const void *data,
2730 int data_len)
2731{
2732 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2733 uint8_t i, feature_sets, max_feature_sets;
2734 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2735 struct sk_buff *reply_skb;
2736 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2737 int ret;
2738
2739 ENTER_DEV(wdev->netdev);
2740
2741 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2742 hdd_err("Command not allowed in FTM mode");
2743 return -EPERM;
2744 }
2745
2746 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302747 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302748 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302749
2750 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2751 data, data_len, NULL)) {
2752 hdd_err("Invalid ATTR");
2753 return -EINVAL;
2754 }
2755
2756 /* Parse and fetch max feature set */
2757 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2758 hdd_err("Attr max feature set size failed");
2759 return -EINVAL;
2760 }
2761 max_feature_sets = nla_get_u32(tb[
2762 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002763 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302764
2765 /* Fill feature combination matrix */
2766 feature_sets = 0;
2767 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002768 WIFI_FEATURE_P2P;
2769 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2770 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302771 /* Add more feature combinations here */
2772
2773 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002774 hdd_debug("Number of feature sets: %d", feature_sets);
2775 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302776 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002777 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302778
2779 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2780 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2781 if (!reply_skb) {
2782 hdd_err("Feature set matrix: buffer alloc fail");
2783 return -ENOMEM;
2784 }
2785
2786 if (nla_put_u32(reply_skb,
2787 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2788 feature_sets) ||
2789 nla_put(reply_skb,
2790 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2791 sizeof(u32) * feature_sets,
2792 feature_set_matrix)) {
2793 hdd_err("nla put fail");
2794 kfree_skb(reply_skb);
2795 return -EINVAL;
2796 }
2797 return cfg80211_vendor_cmd_reply(reply_skb);
2798}
2799
2800/**
2801 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2802 * @wiphy: pointer to wireless wiphy structure.
2803 * @wdev: pointer to wireless_dev structure.
2804 * @data: Pointer to the data to be passed via vendor interface
2805 * @data_len:Length of the data to be passed
2806 *
2807 * Retrieves the concurrency feature set matrix
2808 *
2809 * Return: 0 on success, negative errno on failure
2810 */
2811static int
2812wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2813 struct wireless_dev *wdev,
2814 const void *data,
2815 int data_len)
2816{
2817 int ret;
2818
2819 cds_ssr_protect(__func__);
2820 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2821 data, data_len);
2822 cds_ssr_unprotect(__func__);
2823
2824 return ret;
2825}
2826
2827/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2829 * @feature_flags: pointer to the byte array of features.
2830 * @feature: Feature to be turned ON in the byte array.
2831 *
2832 * Return: None
2833 *
2834 * This is called to turn ON or SET the feature flag for the requested feature.
2835 **/
2836#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002837static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2838 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839{
2840 uint32_t index;
2841 uint8_t bit_mask;
2842
2843 index = feature / NUM_BITS_IN_BYTE;
2844 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2845 feature_flags[index] |= bit_mask;
2846}
2847
2848/**
2849 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2850 * @wiphy: pointer to wireless wiphy structure.
2851 * @wdev: pointer to wireless_dev structure.
2852 * @data: Pointer to the data to be passed via vendor interface
2853 * @data_len:Length of the data to be passed
2854 *
2855 * This is called when wlan driver needs to send supported feature set to
2856 * supplicant upon a request/query from the supplicant.
2857 *
2858 * Return: Return the Success or Failure code.
2859 **/
2860#define MAX_CONCURRENT_CHAN_ON_24G 2
2861#define MAX_CONCURRENT_CHAN_ON_5G 2
2862static int
2863__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2864 struct wireless_dev *wdev,
2865 const void *data, int data_len)
2866{
2867 struct sk_buff *skb = NULL;
2868 uint32_t dbs_capability = 0;
2869 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302870 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002871 int ret_val;
2872
2873 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2874 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2875
Jeff Johnson1f61b612016-02-12 16:28:33 -08002876 ENTER_DEV(wdev->netdev);
2877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002878 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2879 if (ret_val)
2880 return ret_val;
2881
Anurag Chouhan6d760662016-02-20 16:05:43 +05302882 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883 hdd_err("Command not allowed in FTM mode");
2884 return -EPERM;
2885 }
2886
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002887 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002888 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889 wlan_hdd_cfg80211_set_feature(feature_flags,
2890 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2891 }
2892
2893 wlan_hdd_cfg80211_set_feature(feature_flags,
2894 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002895 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002896 wlan_hdd_cfg80211_set_feature(feature_flags,
2897 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002898
2899 if (wma_is_p2p_lo_capable())
2900 wlan_hdd_cfg80211_set_feature(feature_flags,
2901 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2902
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002903 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2904 NLMSG_HDRLEN);
2905
2906 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002907 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908 return -ENOMEM;
2909 }
2910
2911 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2912 sizeof(feature_flags), feature_flags))
2913 goto nla_put_failure;
2914
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002915 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2916 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302917 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918 if (one_by_one_dbs)
2919 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2920
2921 if (two_by_two_dbs)
2922 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2923
2924 if (!one_by_one_dbs && !two_by_two_dbs)
2925 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2926 } else {
2927 hdd_err("wma_get_dbs_hw_mode failed");
2928 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2929 }
2930
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002931 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932
2933 if (nla_put_u32(skb,
2934 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2935 MAX_CONCURRENT_CHAN_ON_24G))
2936 goto nla_put_failure;
2937
2938 if (nla_put_u32(skb,
2939 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2940 MAX_CONCURRENT_CHAN_ON_5G))
2941 goto nla_put_failure;
2942
2943 return cfg80211_vendor_cmd_reply(skb);
2944
2945nla_put_failure:
2946 kfree_skb(skb);
2947 return -EINVAL;
2948}
2949
2950/**
2951 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2952 * @wiphy: pointer to wireless wiphy structure.
2953 * @wdev: pointer to wireless_dev structure.
2954 * @data: Pointer to the data to be passed via vendor interface
2955 * @data_len:Length of the data to be passed
2956 *
2957 * This is called when wlan driver needs to send supported feature set to
2958 * supplicant upon a request/query from the supplicant.
2959 *
2960 * Return: Return the Success or Failure code.
2961 */
2962static int
2963wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2964 struct wireless_dev *wdev,
2965 const void *data, int data_len)
2966{
2967 int ret;
2968
2969 cds_ssr_protect(__func__);
2970 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2971 data, data_len);
2972 cds_ssr_unprotect(__func__);
2973
2974 return ret;
2975}
2976
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302977#define PARAM_NUM_NW \
2978 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2979#define PARAM_SET_BSSID \
2980 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2981#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2982#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002983
2984/**
2985 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2986 * @wiphy: The wiphy structure
2987 * @wdev: The wireless device
2988 * @data: Data passed by framework
2989 * @data_len: Parameters to be configured passed as data
2990 *
2991 * The roaming related parameters are configured by the framework
2992 * using this interface.
2993 *
2994 * Return: Return either success or failure code.
2995 */
2996static int
2997__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2998 struct wireless_dev *wdev, const void *data, int data_len)
2999{
3000 struct net_device *dev = wdev->netdev;
3001 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3002 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3003 uint8_t session_id;
3004 struct roam_ext_params roam_params;
3005 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303006 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
3008 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
3009 int rem, i;
3010 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08003011 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012 int ret;
3013
Jeff Johnson1f61b612016-02-12 16:28:33 -08003014 ENTER_DEV(dev);
3015
Anurag Chouhan6d760662016-02-20 16:05:43 +05303016 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 hdd_err("Command not allowed in FTM mode");
3018 return -EPERM;
3019 }
3020
3021 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303022 if (ret)
3023 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05303025 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
3026 hdd_err("Driver Modules are closed");
3027 return -EINVAL;
3028 }
3029
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003030 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3031 data, data_len,
3032 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003033 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 return -EINVAL;
3035 }
3036 /* Parse and fetch Command Type*/
3037 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003038 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003039 goto fail;
3040 }
3041 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303042 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
3044 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003045 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003046 goto fail;
3047 }
3048 req_id = nla_get_u32(
3049 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07003050 hdd_debug("Req Id (%d)", req_id);
3051 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 switch (cmd_type) {
3053 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
3054 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303055 if (tb[PARAM_NUM_NW]) {
3056 count = nla_get_u32(
3057 tb[PARAM_NUM_NW]);
3058 } else {
3059 hdd_err("Number of networks is not provided");
3060 goto fail;
3061 }
3062
3063 if (count &&
3064 tb[PRAM_SSID_LIST]) {
3065 nla_for_each_nested(curr_attr,
3066 tb[PRAM_SSID_LIST], rem) {
3067 if (nla_parse(tb2,
3068 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
3069 nla_data(curr_attr), nla_len(curr_attr),
3070 NULL)) {
3071 hdd_err("nla_parse failed");
3072 goto fail;
3073 }
3074 /* Parse and Fetch allowed SSID list*/
3075 if (!tb2[PARAM_LIST_SSID]) {
3076 hdd_err("attr allowed ssid failed");
3077 goto fail;
3078 }
3079 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
3080 /*
3081 * Upper Layers include a null termination
3082 * character. Check for the actual permissible
3083 * length of SSID and also ensure not to copy
3084 * the NULL termination character to the driver
3085 * buffer.
3086 */
3087 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
3088 ((buf_len - 1) <=
3089 SIR_MAC_MAX_SSID_LENGTH)) {
3090 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003091 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303092 tb2[PARAM_LIST_SSID], buf_len - 1);
3093 roam_params.ssid_allowed_list[i].length
3094 = buf_len - 1;
3095 hdd_debug("SSID[%d]: %.*s,length = %d",
3096 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003097 roam_params.ssid_allowed_list[i].length,
3098 roam_params.ssid_allowed_list[i].ssId,
3099 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303100 i++;
3101 } else {
3102 hdd_err("Invalid buffer length");
3103 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 }
3105 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303106 if (i != count) {
3107 hdd_err("Invalid number of SSIDs i = %d, count = %d",
3108 i, count);
3109 goto fail;
3110 }
3111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07003113 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003114 roam_params.num_ssid_allowed_list);
3115 sme_update_roam_params(pHddCtx->hHal, session_id,
3116 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3117 break;
3118 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3119 /* Parse and fetch 5G Boost Threshold */
3120 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003121 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003122 goto fail;
3123 }
3124 roam_params.raise_rssi_thresh_5g = nla_get_s32(
3125 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003126 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003127 roam_params.raise_rssi_thresh_5g);
3128 /* Parse and fetch 5G Penalty Threshold */
3129 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003130 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003131 goto fail;
3132 }
3133 roam_params.drop_rssi_thresh_5g = nla_get_s32(
3134 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003135 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003136 roam_params.drop_rssi_thresh_5g);
3137 /* Parse and fetch 5G Boost Factor */
3138 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003139 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003140 goto fail;
3141 }
3142 roam_params.raise_factor_5g = nla_get_u32(
3143 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003144 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003145 roam_params.raise_factor_5g);
3146 /* Parse and fetch 5G Penalty factor */
3147 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003148 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003149 goto fail;
3150 }
3151 roam_params.drop_factor_5g = nla_get_u32(
3152 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003153 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 roam_params.drop_factor_5g);
3155 /* Parse and fetch 5G Max Boost */
3156 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003157 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158 goto fail;
3159 }
3160 roam_params.max_raise_rssi_5g = nla_get_u32(
3161 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07003162 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 roam_params.max_raise_rssi_5g);
3164 /* Parse and fetch Rssi Diff */
3165 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003166 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 goto fail;
3168 }
3169 roam_params.rssi_diff = nla_get_s32(
3170 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07003171 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 roam_params.rssi_diff);
3173 /* Parse and fetch Alert Rssi Threshold */
3174 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003175 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176 goto fail;
3177 }
3178 roam_params.alert_rssi_threshold = nla_get_u32(
3179 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003180 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003181 roam_params.alert_rssi_threshold);
3182 sme_update_roam_params(pHddCtx->hHal, session_id,
3183 roam_params,
3184 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3185 break;
3186 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3187 /* Parse and fetch Activate Good Rssi Roam */
3188 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003189 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 goto fail;
3191 }
3192 roam_params.good_rssi_roam = nla_get_s32(
3193 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07003194 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195 roam_params.good_rssi_roam);
3196 sme_update_roam_params(pHddCtx->hHal, session_id,
3197 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3198 break;
3199 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3200 /* Parse and fetch number of preferred BSSID */
3201 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003202 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 goto fail;
3204 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003205 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003207 if (count > MAX_BSSID_FAVORED) {
3208 hdd_err("Preferred BSSID count %u exceeds max %u",
3209 count, MAX_BSSID_FAVORED);
3210 goto fail;
3211 }
3212 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003213 i = 0;
3214 nla_for_each_nested(curr_attr,
3215 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3216 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003217
3218 if (i == count) {
3219 hdd_warn("Ignoring excess Preferred BSSID");
3220 break;
3221 }
3222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003223 if (nla_parse(tb2,
3224 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3225 nla_data(curr_attr), nla_len(curr_attr),
3226 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003227 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228 goto fail;
3229 }
3230 /* Parse and fetch MAC address */
3231 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003232 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233 goto fail;
3234 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003235 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303237 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003238 hdd_debug(MAC_ADDRESS_STR,
3239 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 /* Parse and fetch preference factor*/
3241 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003242 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243 goto fail;
3244 }
3245 roam_params.bssid_favored_factor[i] = nla_get_u32(
3246 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003247 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248 roam_params.bssid_favored_factor[i]);
3249 i++;
3250 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003251 if (i < count)
3252 hdd_warn("Num Preferred BSSID %u less than expected %u",
3253 i, count);
3254 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003255 sme_update_roam_params(pHddCtx->hHal, session_id,
3256 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3257 break;
3258 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3259 /* Parse and fetch number of blacklist BSSID */
3260 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003261 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003262 goto fail;
3263 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003264 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003265 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003266 if (count > MAX_BSSID_AVOID_LIST) {
3267 hdd_err("Blacklist BSSID count %u exceeds max %u",
3268 count, MAX_BSSID_AVOID_LIST);
3269 goto fail;
3270 }
3271 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303273
3274 if (count &&
3275 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3276 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3278 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003279
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303280 if (i == count) {
3281 hdd_warn("Ignoring excess Blacklist BSSID");
3282 break;
3283 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003284
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303285 if (nla_parse(tb2,
3286 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3287 nla_data(curr_attr), nla_len(curr_attr),
3288 NULL)) {
3289 hdd_err("nla_parse failed");
3290 goto fail;
3291 }
3292 /* Parse and fetch MAC address */
3293 if (!tb2[PARAM_SET_BSSID]) {
3294 hdd_err("attr blacklist addr failed");
3295 goto fail;
3296 }
3297 nla_memcpy(
3298 roam_params.bssid_avoid_list[i].bytes,
3299 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3300 hdd_debug(MAC_ADDRESS_STR,
3301 MAC_ADDR_ARRAY(
3302 roam_params.bssid_avoid_list[i].bytes));
3303 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003305 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003306 if (i < count)
3307 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3308 i, count);
3309 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310 sme_update_roam_params(pHddCtx->hHal, session_id,
3311 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3312 break;
3313 }
3314 return 0;
3315fail:
3316 return -EINVAL;
3317}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303318#undef PARAM_NUM_NW
3319#undef PARAM_SET_BSSID
3320#undef PRAM_SSID_LIST
3321#undef PARAM_LIST_SSID
3322
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003323
3324/**
3325 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3326 * @wiphy: pointer to wireless wiphy structure.
3327 * @wdev: pointer to wireless_dev structure.
3328 * @data: Pointer to the data to be passed via vendor interface
3329 * @data_len:Length of the data to be passed
3330 *
3331 * Return: Return the Success or Failure code.
3332 */
3333static int
3334wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3335 struct wireless_dev *wdev,
3336 const void *data,
3337 int data_len)
3338{
3339 int ret;
3340
3341 cds_ssr_protect(__func__);
3342 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3343 data, data_len);
3344 cds_ssr_unprotect(__func__);
3345
3346 return ret;
3347}
3348
3349static const struct nla_policy
3350wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3351 +1] = {
3352 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3353};
3354
3355/**
3356 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3357 * @hdd_ctx: HDD context
3358 * @device_mode: device mode
3359 * Return: bool
3360 */
3361static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003362 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003363{
3364 hdd_adapter_t *adapter;
3365 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3366 hdd_ap_ctx_t *ap_ctx;
3367 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303368 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003369
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303370 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003371 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003372 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303373 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003374 adapter = adapter_node->pAdapter;
3375
3376 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003377 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003378 ap_ctx =
3379 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3380
3381 /*
3382 * if there is SAP already running on DFS channel,
3383 * do not disable scan on dfs channels. Note that
3384 * with SAP on DFS, there cannot be conurrency on
3385 * single radio. But then we can have multiple
3386 * radios !!
3387 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003388 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3389 hdd_ctx->hdd_pdev,
3390 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003391 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003392 return true;
3393 }
3394 }
3395
3396 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003397 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003398 sta_ctx =
3399 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3400
3401 /*
3402 * if STA is already connected on DFS channel,
3403 * do not disable scan on dfs channels
3404 */
3405 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003406 (CHANNEL_STATE_DFS ==
3407 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3408 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003409 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003410 return true;
3411 }
3412 }
3413
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303414 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 adapter_node,
3416 &next);
3417 adapter_node = next;
3418 }
3419
3420 return false;
3421}
3422
3423/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003424 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003425 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003426 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003427 *
3428 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003429 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003430 * Fails the disable request if any device is active on a DFS channel.
3431 *
3432 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003433 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003434
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003435int wlan_hdd_enable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3436 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003437{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303438 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003439 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003440
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003441 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
3442 hdd_info("DFS channels are already %s",
3443 enable_dfs_channels ? "enabled" : "disabled");
3444 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003445 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003446
3447 if (!enable_dfs_channels) {
3448 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3449 QDF_STA_MODE);
3450 if (err)
3451 return -EOPNOTSUPP;
3452
3453 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3454 QDF_SAP_MODE);
3455 if (err)
3456 return -EOPNOTSUPP;
3457 }
3458
3459 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
3460
3461 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3462
3463 /* pass dfs channel status to regulatory component */
3464 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
3465 enable_dfs_channels);
3466
3467 if (QDF_IS_STATUS_ERROR(status))
3468 hdd_err("Failed to %s DFS channels",
3469 enable_dfs_channels ? "enable" : "disable");
3470
3471 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003472}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003474/**
3475 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3476 * @wiphy: corestack handler
3477 * @wdev: wireless device
3478 * @data: data
3479 * @data_len: data length
3480 * Return: success(0) or reason code for failure
3481 */
3482static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3483 struct wireless_dev *wdev,
3484 const void *data,
3485 int data_len)
3486{
3487 struct net_device *dev = wdev->netdev;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003488 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3489 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3490 int ret_val;
3491 uint32_t no_dfs_flag = 0;
3492
Jeff Johnson1f61b612016-02-12 16:28:33 -08003493 ENTER_DEV(dev);
3494
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003495 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303496 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003497 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003498
3499 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3500 data, data_len,
3501 wlan_hdd_set_no_dfs_flag_config_policy)) {
3502 hdd_err("invalid attr");
3503 return -EINVAL;
3504 }
3505
3506 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3507 hdd_err("attr dfs flag failed");
3508 return -EINVAL;
3509 }
3510
3511 no_dfs_flag = nla_get_u32(
3512 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3513
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003514 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003515
3516 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003517 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003518 return -EINVAL;
3519 }
3520
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003521 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003522 return ret_val;
3523}
3524
3525/**
3526 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3527 *
3528 * @wiphy: wiphy device pointer
3529 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003530 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531 * @data_len: Buffer length
3532 *
3533 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3534 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3535 *
3536 * Return: EOK or other error codes.
3537 */
3538
3539static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3540 struct wireless_dev *wdev,
3541 const void *data,
3542 int data_len)
3543{
3544 int ret;
3545
3546 cds_ssr_protect(__func__);
3547 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3548 data, data_len);
3549 cds_ssr_unprotect(__func__);
3550
3551 return ret;
3552}
3553
Manikandan Mohan80dea792016-04-28 16:36:48 -07003554static const struct nla_policy
3555wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3556 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3557};
3558
3559/**
3560 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3561 * @wiphy: wiphy device pointer
3562 * @wdev: wireless device pointer
3563 * @data: Vendor command data buffer
3564 * @data_len: Buffer length
3565 *
3566 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3567 * setup WISA Mode features.
3568 *
3569 * Return: Success(0) or reason code for failure
3570 */
3571static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3572 struct wireless_dev *wdev, const void *data, int data_len)
3573{
3574 struct net_device *dev = wdev->netdev;
3575 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3576 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3577 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3578 struct sir_wisa_params wisa;
3579 int ret_val;
3580 QDF_STATUS status;
3581 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003582 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3583 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003584
3585 ENTER_DEV(dev);
3586 ret_val = wlan_hdd_validate_context(hdd_ctx);
3587 if (ret_val)
3588 goto err;
3589
3590 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3591 hdd_err("Command not allowed in FTM mode");
3592 return -EPERM;
3593 }
3594
3595 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3596 wlan_hdd_wisa_cmd_policy)) {
3597 hdd_err("Invalid WISA cmd attributes");
3598 ret_val = -EINVAL;
3599 goto err;
3600 }
3601 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3602 hdd_err("Invalid WISA mode");
3603 ret_val = -EINVAL;
3604 goto err;
3605 }
3606
3607 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003608 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003609 wisa.mode = wisa_mode;
3610 wisa.vdev_id = adapter->sessionId;
3611 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003612 if (!QDF_IS_STATUS_SUCCESS(status)) {
3613 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003614 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003615 }
3616 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003617 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003618 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3619 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003620 adapter->sessionId),
3621 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003622err:
3623 EXIT();
3624 return ret_val;
3625}
3626
3627/**
3628 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3629 * @wiphy: corestack handler
3630 * @wdev: wireless device
3631 * @data: data
3632 * @data_len: data length
3633 *
3634 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3635 * setup WISA mode features.
3636 *
3637 * Return: Success(0) or reason code for failure
3638 */
3639static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3640 struct wireless_dev *wdev,
3641 const void *data,
3642 int data_len)
3643{
3644 int ret;
3645
3646 cds_ssr_protect(__func__);
3647 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3648 cds_ssr_unprotect(__func__);
3649
3650 return ret;
3651}
3652
Anurag Chouhan96919482016-07-13 16:36:57 +05303653/*
3654 * define short names for the global vendor params
3655 * used by __wlan_hdd_cfg80211_get_station_cmd()
3656 */
3657#define STATION_INVALID \
3658 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3659#define STATION_INFO \
3660 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3661#define STATION_ASSOC_FAIL_REASON \
3662 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3663#define STATION_MAX \
3664 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3665
3666static const struct nla_policy
3667hdd_get_station_policy[STATION_MAX + 1] = {
3668 [STATION_INFO] = {.type = NLA_FLAG},
3669 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3670};
3671
3672/**
3673 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3674 * @hdd_ctx: HDD context within host driver
3675 * @wdev: wireless device
3676 *
3677 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3678 * Validate cmd attributes and send the station info to upper layers.
3679 *
3680 * Return: Success(0) or reason code for failure
3681 */
3682static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3683 hdd_adapter_t *adapter)
3684{
3685 struct sk_buff *skb = NULL;
3686 uint32_t nl_buf_len;
3687 hdd_station_ctx_t *hdd_sta_ctx;
3688
3689 nl_buf_len = NLMSG_HDRLEN;
3690 nl_buf_len += sizeof(uint32_t);
3691 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3692
3693 if (!skb) {
3694 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3695 return -ENOMEM;
3696 }
3697
3698 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3699
3700 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3701 hdd_sta_ctx->conn_info.assoc_status_code)) {
3702 hdd_err("put fail");
3703 goto fail;
3704 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303705
3706 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3707 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3708 hdd_sta_ctx->conn_info.cca)) {
3709 hdd_err("put fail");
3710 goto fail;
3711 }
3712
Anurag Chouhan96919482016-07-13 16:36:57 +05303713 return cfg80211_vendor_cmd_reply(skb);
3714fail:
3715 if (skb)
3716 kfree_skb(skb);
3717 return -EINVAL;
3718}
3719
3720/**
3721 * hdd_map_auth_type() - transform auth type specific to
3722 * vendor command
3723 * @auth_type: csr auth type
3724 *
3725 * Return: Success(0) or reason code for failure
3726 */
3727static int hdd_convert_auth_type(uint32_t auth_type)
3728{
3729 uint32_t ret_val;
3730
3731 switch (auth_type) {
3732 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3733 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3734 break;
3735 case eCSR_AUTH_TYPE_SHARED_KEY:
3736 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3737 break;
3738 case eCSR_AUTH_TYPE_WPA:
3739 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3740 break;
3741 case eCSR_AUTH_TYPE_WPA_PSK:
3742 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3743 break;
3744 case eCSR_AUTH_TYPE_AUTOSWITCH:
3745 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3746 break;
3747 case eCSR_AUTH_TYPE_WPA_NONE:
3748 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3749 break;
3750 case eCSR_AUTH_TYPE_RSN:
3751 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3752 break;
3753 case eCSR_AUTH_TYPE_RSN_PSK:
3754 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3755 break;
3756 case eCSR_AUTH_TYPE_FT_RSN:
3757 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3758 break;
3759 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3760 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3761 break;
3762 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3763 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3764 break;
3765 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3766 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3767 break;
3768 case eCSR_AUTH_TYPE_CCKM_WPA:
3769 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3770 break;
3771 case eCSR_AUTH_TYPE_CCKM_RSN:
3772 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3773 break;
3774 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3775 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3776 break;
3777 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3778 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3779 break;
3780 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3781 case eCSR_AUTH_TYPE_FAILED:
3782 case eCSR_AUTH_TYPE_NONE:
3783 default:
3784 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3785 break;
3786 }
3787 return ret_val;
3788}
3789
3790/**
3791 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3792 * vendor command
3793 * @dot11mode: dot11mode
3794 *
3795 * Return: Success(0) or reason code for failure
3796 */
3797static int hdd_convert_dot11mode(uint32_t dot11mode)
3798{
3799 uint32_t ret_val;
3800
3801 switch (dot11mode) {
3802 case eCSR_CFG_DOT11_MODE_11A:
3803 ret_val = QCA_WLAN_802_11_MODE_11A;
3804 break;
3805 case eCSR_CFG_DOT11_MODE_11B:
3806 ret_val = QCA_WLAN_802_11_MODE_11B;
3807 break;
3808 case eCSR_CFG_DOT11_MODE_11G:
3809 ret_val = QCA_WLAN_802_11_MODE_11G;
3810 break;
3811 case eCSR_CFG_DOT11_MODE_11N:
3812 ret_val = QCA_WLAN_802_11_MODE_11N;
3813 break;
3814 case eCSR_CFG_DOT11_MODE_11AC:
3815 ret_val = QCA_WLAN_802_11_MODE_11AC;
3816 break;
3817 case eCSR_CFG_DOT11_MODE_AUTO:
3818 case eCSR_CFG_DOT11_MODE_ABG:
3819 default:
3820 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3821 }
3822 return ret_val;
3823}
3824
3825/**
3826 * hdd_add_tx_bitrate() - add tx bitrate attribute
3827 * @skb: pointer to sk buff
3828 * @hdd_sta_ctx: pointer to hdd station context
3829 * @idx: attribute index
3830 *
3831 * Return: Success(0) or reason code for failure
3832 */
3833static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3834 hdd_station_ctx_t *hdd_sta_ctx,
3835 int idx)
3836{
3837 struct nlattr *nla_attr;
3838 uint32_t bitrate, bitrate_compat;
3839
3840 nla_attr = nla_nest_start(skb, idx);
3841 if (!nla_attr)
3842 goto fail;
3843 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3844 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3845
3846 /* report 16-bit bitrate only if we can */
3847 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3848 if (bitrate > 0 &&
3849 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3850 hdd_err("put fail");
3851 goto fail;
3852 }
3853 if (bitrate_compat > 0 &&
3854 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3855 hdd_err("put fail");
3856 goto fail;
3857 }
3858 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3859 hdd_sta_ctx->conn_info.txrate.nss)) {
3860 hdd_err("put fail");
3861 goto fail;
3862 }
3863 nla_nest_end(skb, nla_attr);
3864 return 0;
3865fail:
3866 return -EINVAL;
3867}
3868
3869/**
3870 * hdd_add_sta_info() - add station info 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_sta_info(struct sk_buff *skb,
3878 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3879{
3880 struct nlattr *nla_attr;
3881
3882 nla_attr = nla_nest_start(skb, idx);
3883 if (!nla_attr)
3884 goto fail;
3885 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3886 (hdd_sta_ctx->conn_info.signal + 100))) {
3887 hdd_err("put fail");
3888 goto fail;
3889 }
3890 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3891 goto fail;
3892 nla_nest_end(skb, nla_attr);
3893 return 0;
3894fail:
3895 return -EINVAL;
3896}
3897
3898/**
3899 * hdd_add_survey_info() - add survey info attribute
3900 * @skb: pointer to sk buff
3901 * @hdd_sta_ctx: pointer to hdd station context
3902 * @idx: attribute index
3903 *
3904 * Return: Success(0) or reason code for failure
3905 */
3906static int32_t hdd_add_survey_info(struct sk_buff *skb,
3907 hdd_station_ctx_t *hdd_sta_ctx,
3908 int idx)
3909{
3910 struct nlattr *nla_attr;
3911
3912 nla_attr = nla_nest_start(skb, idx);
3913 if (!nla_attr)
3914 goto fail;
3915 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3916 hdd_sta_ctx->conn_info.freq) ||
3917 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3918 (hdd_sta_ctx->conn_info.noise + 100))) {
3919 hdd_err("put fail");
3920 goto fail;
3921 }
3922 nla_nest_end(skb, nla_attr);
3923 return 0;
3924fail:
3925 return -EINVAL;
3926}
3927
3928/**
3929 * hdd_add_link_standard_info() - add link info attribute
3930 * @skb: pointer to sk buff
3931 * @hdd_sta_ctx: pointer to hdd station context
3932 * @idx: attribute index
3933 *
3934 * Return: Success(0) or reason code for failure
3935 */
3936static int32_t
3937hdd_add_link_standard_info(struct sk_buff *skb,
3938 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3939{
3940 struct nlattr *nla_attr;
3941
3942 nla_attr = nla_nest_start(skb, idx);
3943 if (!nla_attr)
3944 goto fail;
3945 if (nla_put(skb,
3946 NL80211_ATTR_SSID,
3947 hdd_sta_ctx->conn_info.SSID.SSID.length,
3948 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3949 hdd_err("put fail");
3950 goto fail;
3951 }
3952 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3953 goto fail;
3954 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3955 goto fail;
3956 nla_nest_end(skb, nla_attr);
3957 return 0;
3958fail:
3959 return -EINVAL;
3960}
3961
3962/**
3963 * hdd_add_ap_standard_info() - add ap info attribute
3964 * @skb: pointer to sk buff
3965 * @hdd_sta_ctx: pointer to hdd station context
3966 * @idx: attribute index
3967 *
3968 * Return: Success(0) or reason code for failure
3969 */
3970static int32_t
3971hdd_add_ap_standard_info(struct sk_buff *skb,
3972 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3973{
3974 struct nlattr *nla_attr;
3975
3976 nla_attr = nla_nest_start(skb, idx);
3977 if (!nla_attr)
3978 goto fail;
3979 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3980 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3981 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3982 &hdd_sta_ctx->conn_info.vht_caps)) {
3983 hdd_err("put fail");
3984 goto fail;
3985 }
3986 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3987 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3988 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3989 &hdd_sta_ctx->conn_info.ht_caps)) {
3990 hdd_err("put fail");
3991 goto fail;
3992 }
3993 nla_nest_end(skb, nla_attr);
3994 return 0;
3995fail:
3996 return -EINVAL;
3997}
3998
3999/**
4000 * hdd_get_station_info() - send BSS information to supplicant
4001 * @hdd_ctx: pointer to hdd context
4002 * @adapter: pointer to adapter
4003 *
4004 * Return: 0 if success else error status
4005 */
4006static int hdd_get_station_info(hdd_context_t *hdd_ctx,
4007 hdd_adapter_t *adapter)
4008{
4009 struct sk_buff *skb = NULL;
4010 uint8_t *tmp_hs20 = NULL;
4011 uint32_t nl_buf_len;
4012 hdd_station_ctx_t *hdd_sta_ctx;
4013
4014 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4015
4016 nl_buf_len = NLMSG_HDRLEN;
4017 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
4018 sizeof(hdd_sta_ctx->conn_info.freq) +
4019 sizeof(hdd_sta_ctx->conn_info.noise) +
4020 sizeof(hdd_sta_ctx->conn_info.signal) +
4021 (sizeof(uint32_t) * 2) +
4022 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
4023 sizeof(hdd_sta_ctx->conn_info.roam_count) +
4024 sizeof(hdd_sta_ctx->conn_info.authType) +
4025 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
4026 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
4027 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
4028 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
4029 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
4030 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
4031 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
4032 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
4033 1);
4034 }
4035 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
4036 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
4037 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
4038 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
4039
4040
4041 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
4042 if (!skb) {
4043 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
4044 return -ENOMEM;
4045 }
4046
4047 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
4048 LINK_INFO_STANDARD_NL80211_ATTR)) {
4049 hdd_err("put fail");
4050 goto fail;
4051 }
4052 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
4053 AP_INFO_STANDARD_NL80211_ATTR)) {
4054 hdd_err("put fail");
4055 goto fail;
4056 }
4057 if (nla_put_u32(skb, INFO_ROAM_COUNT,
4058 hdd_sta_ctx->conn_info.roam_count) ||
4059 nla_put_u32(skb, INFO_AKM,
4060 hdd_convert_auth_type(
4061 hdd_sta_ctx->conn_info.authType)) ||
4062 nla_put_u32(skb, WLAN802_11_MODE,
4063 hdd_convert_dot11mode(
4064 hdd_sta_ctx->conn_info.dot11Mode))) {
4065 hdd_err("put fail");
4066 goto fail;
4067 }
4068 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
4069 if (nla_put(skb, HT_OPERATION,
4070 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
4071 &hdd_sta_ctx->conn_info.ht_operation)) {
4072 hdd_err("put fail");
4073 goto fail;
4074 }
4075 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
4076 if (nla_put(skb, VHT_OPERATION,
4077 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
4078 &hdd_sta_ctx->conn_info.vht_operation)) {
4079 hdd_err("put fail");
4080 goto fail;
4081 }
4082 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
4083 if (nla_put(skb, AP_INFO_HS20_INDICATION,
4084 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
4085 tmp_hs20 + 1)) {
4086 hdd_err("put fail");
4087 goto fail;
4088 }
4089
4090 return cfg80211_vendor_cmd_reply(skb);
4091fail:
4092 if (skb)
4093 kfree_skb(skb);
4094 return -EINVAL;
4095}
4096
4097/**
4098 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4099 * @wiphy: corestack handler
4100 * @wdev: wireless device
4101 * @data: data
4102 * @data_len: data length
4103 *
4104 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4105 * Validate cmd attributes and send the station info to upper layers.
4106 *
4107 * Return: Success(0) or reason code for failure
4108 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05304109static int
Anurag Chouhan96919482016-07-13 16:36:57 +05304110__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4111 struct wireless_dev *wdev,
4112 const void *data,
4113 int data_len)
4114{
4115 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4116 struct net_device *dev = wdev->netdev;
4117 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4118 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
4119 int32_t status;
4120
4121 ENTER_DEV(dev);
4122 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4123 hdd_err("Command not allowed in FTM mode");
4124 status = -EPERM;
4125 goto out;
4126 }
4127
4128 status = wlan_hdd_validate_context(hdd_ctx);
4129 if (0 != status)
4130 goto out;
4131
4132
4133 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
4134 data, data_len, NULL);
4135 if (status) {
4136 hdd_err("Invalid ATTR");
4137 goto out;
4138 }
4139
4140 /* Parse and fetch Command Type*/
4141 if (tb[STATION_INFO]) {
4142 status = hdd_get_station_info(hdd_ctx, adapter);
4143 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
4144 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
4145 } else {
4146 hdd_err("get station info cmd type failed");
4147 status = -EINVAL;
4148 goto out;
4149 }
4150 EXIT();
4151out:
4152 return status;
4153}
4154
4155/**
4156 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4157 * @wiphy: corestack handler
4158 * @wdev: wireless device
4159 * @data: data
4160 * @data_len: data length
4161 *
4162 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4163 * Validate cmd attributes and send the station info to upper layers.
4164 *
4165 * Return: Success(0) or reason code for failure
4166 */
4167static int32_t
4168hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4169 struct wireless_dev *wdev,
4170 const void *data,
4171 int data_len)
4172{
4173 int ret;
4174
4175 cds_ssr_protect(__func__);
4176 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
4177 cds_ssr_unprotect(__func__);
4178
4179 return ret;
4180}
4181
4182/*
4183 * undef short names defined for get station command
4184 * used by __wlan_hdd_cfg80211_get_station_cmd()
4185 */
4186#undef STATION_INVALID
4187#undef STATION_INFO
4188#undef STATION_ASSOC_FAIL_REASON
4189#undef STATION_MAX
4190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004191#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4192/**
4193 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4194 * @wiphy: pointer to wireless wiphy structure.
4195 * @wdev: pointer to wireless_dev structure.
4196 * @data: Pointer to the Key data
4197 * @data_len:Length of the data passed
4198 *
4199 * This is called when wlan driver needs to save the keys received via
4200 * vendor specific command.
4201 *
4202 * Return: Return the Success or Failure code.
4203 */
4204static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4205 struct wireless_dev *wdev,
4206 const void *data, int data_len)
4207{
4208 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4209 struct net_device *dev = wdev->netdev;
4210 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4211 hdd_context_t *hdd_ctx_ptr;
4212 int status;
4213
Jeff Johnson1f61b612016-02-12 16:28:33 -08004214 ENTER_DEV(dev);
4215
Anurag Chouhan6d760662016-02-20 16:05:43 +05304216 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004217 hdd_err("Command not allowed in FTM mode");
4218 return -EPERM;
4219 }
4220
4221 if ((data == NULL) || (data_len == 0) ||
4222 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004223 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 return -EINVAL;
4225 }
4226
4227 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4228 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004229 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004230 return -EINVAL;
4231 }
4232
4233 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304234 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004235 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004236 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4237 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004238 true,
4239 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304240 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4241 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004242 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4243 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4244 return 0;
4245}
4246
4247/**
4248 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4249 * @wiphy: pointer to wireless wiphy structure.
4250 * @wdev: pointer to wireless_dev structure.
4251 * @data: Pointer to the Key data
4252 * @data_len:Length of the data passed
4253 *
4254 * This is called when wlan driver needs to save the keys received via
4255 * vendor specific command.
4256 *
4257 * Return: Return the Success or Failure code.
4258 */
4259static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4260 struct wireless_dev *wdev,
4261 const void *data, int data_len)
4262{
4263 int ret;
4264
4265 cds_ssr_protect(__func__);
4266 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4267 cds_ssr_unprotect(__func__);
4268
4269 return ret;
4270}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004271#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272
4273static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4274 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4275 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4276 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004277 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004278};
4279
4280/**
4281 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4282 * @wiphy: pointer to wireless wiphy structure.
4283 * @wdev: pointer to wireless_dev structure.
4284 * @data: Pointer to the data to be passed via vendor interface
4285 * @data_len:Length of the data to be passed
4286 *
4287 * This is called when wlan driver needs to send wifi driver related info
4288 * (driver/fw version) to the user space application upon request.
4289 *
4290 * Return: Return the Success or Failure code.
4291 */
4292static int
4293__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4294 struct wireless_dev *wdev,
4295 const void *data, int data_len)
4296{
4297 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4298 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004299 tSirVersionString driver_version;
4300 tSirVersionString firmware_version;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004301 const char *hw_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004302 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004303 uint32_t sub_id = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004304 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004305 struct sk_buff *reply_skb;
4306 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004307
Jeff Johnson1f61b612016-02-12 16:28:33 -08004308 ENTER_DEV(wdev->netdev);
4309
Anurag Chouhan6d760662016-02-20 16:05:43 +05304310 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004311 hdd_err("Command not allowed in FTM mode");
4312 return -EPERM;
4313 }
4314
4315 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304316 if (status)
4317 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004318
4319 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4320 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004321 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322 return -EINVAL;
4323 }
4324
4325 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004326 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004327 strlcpy(driver_version, QWLAN_VERSIONSTR,
4328 sizeof(driver_version));
4329 skb_len += strlen(driver_version) + 1;
4330 count++;
4331 }
4332
4333 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004334 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4336 &crmid);
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004337 sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
4338 hw_version = hdd_ctx->target_hw_name;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004339 snprintf(firmware_version, sizeof(firmware_version),
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004340 "FW:%d.%d.%d.%d.%d HW:%s", major_spid, minor_spid,
4341 siid, crmid, sub_id, hw_version);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004342 skb_len += strlen(firmware_version) + 1;
4343 count++;
4344 }
4345
4346 if (count == 0) {
4347 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348 return -EINVAL;
4349 }
4350
Ryan Hsu7ac88852016-04-28 10:20:34 -07004351 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4352 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004354 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004355 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004356 return -ENOMEM;
4357 }
4358
Ryan Hsu7ac88852016-04-28 10:20:34 -07004359 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4360 if (nla_put_string(reply_skb,
4361 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4362 driver_version))
4363 goto error_nla_fail;
4364 }
4365
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304366 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004367 if (nla_put_string(reply_skb,
4368 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4369 firmware_version))
4370 goto error_nla_fail;
4371 }
4372
4373 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4374 if (nla_put_u32(reply_skb,
4375 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4376 hdd_ctx->radio_index))
4377 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 }
4379
4380 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004381
4382error_nla_fail:
4383 hdd_err("nla put fail");
4384 kfree_skb(reply_skb);
4385 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004386}
4387
4388/**
4389 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4390 * @wiphy: pointer to wireless wiphy structure.
4391 * @wdev: pointer to wireless_dev structure.
4392 * @data: Pointer to the data to be passed via vendor interface
4393 * @data_len:Length of the data to be passed
4394 *
4395 * This is called when wlan driver needs to send wifi driver related info
4396 * (driver/fw version) to the user space application upon request.
4397 *
4398 * Return: Return the Success or Failure code.
4399 */
4400static int
4401wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4402 struct wireless_dev *wdev,
4403 const void *data, int data_len)
4404{
4405 int ret;
4406
4407 cds_ssr_protect(__func__);
4408 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4409 cds_ssr_unprotect(__func__);
4410
4411 return ret;
4412}
4413
4414/**
4415 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4416 * @wiphy: pointer to wireless wiphy structure.
4417 * @wdev: pointer to wireless_dev structure.
4418 * @data: Pointer to the data to be passed via vendor interface
4419 * @data_len:Length of the data to be passed
4420 *
4421 * This is called by userspace to know the supported logger features
4422 *
4423 * Return: Return the Success or Failure code.
4424 */
4425static int
4426__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4427 struct wireless_dev *wdev,
4428 const void *data, int data_len)
4429{
4430 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4431 int status;
4432 uint32_t features;
4433 struct sk_buff *reply_skb = NULL;
4434
Jeff Johnson1f61b612016-02-12 16:28:33 -08004435 ENTER_DEV(wdev->netdev);
4436
Anurag Chouhan6d760662016-02-20 16:05:43 +05304437 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004438 hdd_err("Command not allowed in FTM mode");
4439 return -EPERM;
4440 }
4441
4442 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304443 if (status)
4444 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004445
4446 features = 0;
4447
4448 if (hdd_is_memdump_supported())
4449 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4450 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4451 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4452 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4453
4454 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4455 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4456 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004457 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004458 return -ENOMEM;
4459 }
4460
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004461 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004462 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4463 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004464 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004465 kfree_skb(reply_skb);
4466 return -EINVAL;
4467 }
4468
4469 return cfg80211_vendor_cmd_reply(reply_skb);
4470}
4471
4472/**
4473 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4474 * @wiphy: pointer to wireless wiphy structure.
4475 * @wdev: pointer to wireless_dev structure.
4476 * @data: Pointer to the data to be passed via vendor interface
4477 * @data_len:Length of the data to be passed
4478 *
4479 * This is called by userspace to know the supported logger features
4480 *
4481 * Return: Return the Success or Failure code.
4482 */
4483static int
4484wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4485 struct wireless_dev *wdev,
4486 const void *data, int data_len)
4487{
4488 int ret;
4489
4490 cds_ssr_protect(__func__);
4491 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4492 data, data_len);
4493 cds_ssr_unprotect(__func__);
4494
4495 return ret;
4496}
4497
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004498#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499/**
4500 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304501 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 * @bssid: pointer to bssid of roamed AP.
4503 * @req_rsn_ie: Pointer to request RSN IE
4504 * @req_rsn_len: Length of the request RSN IE
4505 * @rsp_rsn_ie: Pointer to response RSN IE
4506 * @rsp_rsn_len: Length of the response RSN IE
4507 * @roam_info_ptr: Pointer to the roaming related information
4508 *
4509 * This is called when wlan driver needs to send the roaming and
4510 * authorization information after roaming.
4511 *
4512 * The information that would be sent is the request RSN IE, response
4513 * RSN IE and BSSID of the newly roamed AP.
4514 *
4515 * If the Authorized status is authenticated, then additional parameters
4516 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4517 * supplicant.
4518 *
4519 * The supplicant upon receiving this event would ignore the legacy
4520 * cfg80211_roamed call and use the entire information from this event.
4521 * The cfg80211_roamed should still co-exist since the kernel will
4522 * make use of the parameters even if the supplicant ignores it.
4523 *
4524 * Return: Return the Success or Failure code.
4525 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304526int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004527 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4528 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4529{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304530 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004531 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004532 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004533 ENTER();
4534
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304535 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004536 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004537
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004538 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004539 !roam_info_ptr->roamSynchInProgress)
4540 return 0;
4541
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004542 /*
4543 * The user space has issued a disconnect when roaming is in
4544 * progress. The disconnect should be honored gracefully.
4545 * If the roaming is complete and the roam event is sent
4546 * back to the user space, it will get confused as it is
4547 * expecting a disconnect event. So, do not send the event
4548 * and handle the disconnect later.
4549 */
4550 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004551 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004552 return 0;
4553 }
4554
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004555 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304556 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004557 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4558 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4559 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004560 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004561 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4562 GFP_KERNEL);
4563
4564 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004565 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004566 return -EINVAL;
4567 }
4568
4569 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4570 ETH_ALEN, bssid) ||
4571 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4572 req_rsn_len, req_rsn_ie) ||
4573 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4574 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004575 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576 goto nla_put_failure;
4577 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004578 if (roam_info_ptr->synchAuthStatus ==
4579 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004580 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004581 if (nla_put_u8(skb,
4582 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4583 hdd_err("nla put fail");
4584 goto nla_put_failure;
4585 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004586 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4587 /* if FT or CCKM connection: dont send replay counter */
4588 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4589 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4590 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4591 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4592 nla_put(skb,
4593 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4594 SIR_REPLAY_CTR_LEN,
4595 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004596 hdd_err("non FT/non CCKM connection");
4597 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004598 goto nla_put_failure;
4599 }
4600 if (nla_put(skb,
4601 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4602 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4603 nla_put(skb,
4604 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4605 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4606 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004607 goto nla_put_failure;
4608 }
4609 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004610 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004611 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4612 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004613 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004614 goto nla_put_failure;
4615 }
4616 }
4617
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304618 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4619 roam_info_ptr->synchAuthStatus,
4620 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004621
4622 /*
4623 * Add subnet change status if subnet has changed
4624 * 0 = unchanged
4625 * 1 = changed
4626 * 2 = unknown
4627 */
4628 if (roam_info_ptr->subnet_change_status) {
4629 if (nla_put_u8(skb,
4630 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4631 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004632 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004633 goto nla_put_failure;
4634 }
4635 }
4636
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637 cfg80211_vendor_event(skb, GFP_KERNEL);
4638 return 0;
4639
4640nla_put_failure:
4641 kfree_skb(skb);
4642 return -EINVAL;
4643}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004644#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004645
lifeng907edd62017-05-12 10:10:36 +08004646#define ANT_DIV_PROBE_PERIOD \
4647 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
4648#define ANT_DIV_STAY_PERIOD \
4649 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
4650#define ANT_DIV_SNR_DIFF \
4651 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
4652#define ANT_DIV_PROBE_DWELL_TIME \
4653 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
4654#define ANT_DIV_MGMT_SNR_WEIGHT \
4655 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
4656#define ANT_DIV_DATA_SNR_WEIGHT \
4657 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
4658#define ANT_DIV_ACK_SNR_WEIGHT \
4659 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660static const struct nla_policy
4661wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4662
4663 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4664 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4665 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304666 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304667 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4668 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004669 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4670 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4671 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4672 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4673 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304674 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08004675 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
4676 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
4677 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
4678 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
4679 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
4680 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
4681 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004682};
4683
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304685 * wlan_hdd_add_qcn_ie() - Add QCN IE to a given IE buffer
4686 * @ie_data: IE buffer
4687 * @ie_len: length of the @ie_data
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304688 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304689 * Return: QDF_STATUS
4690 */
4691static QDF_STATUS wlan_hdd_add_qcn_ie(uint8_t *ie_data, uint16_t *ie_len)
4692{
4693 tDot11fIEQCN_IE qcn_ie;
4694 uint8_t qcn_ie_hdr[QCN_IE_HDR_LEN]
4695 = {IE_EID_VENDOR, DOT11F_IE_QCN_IE_MAX_LEN,
4696 0x8C, 0xFD, 0xF0, 0x1};
4697
4698 if (((*ie_len) + QCN_IE_HDR_LEN +
4699 QCN_IE_VERSION_SUBATTR_DATA_LEN) > MAX_DEFAULT_SCAN_IE_LEN) {
4700 hdd_err("IE buffer not enough for QCN IE");
4701 return QDF_STATUS_E_FAILURE;
4702 }
4703
4704 /* Add QCN IE header */
4705 qdf_mem_copy(ie_data + (*ie_len), qcn_ie_hdr, QCN_IE_HDR_LEN);
4706 (*ie_len) += QCN_IE_HDR_LEN;
4707
4708 /* Retrieve Version sub-attribute data */
4709 populate_dot11f_qcn_ie(&qcn_ie);
4710
4711 /* Add QCN IE data[version sub attribute] */
4712 qdf_mem_copy(ie_data + (*ie_len), qcn_ie.version,
4713 (QCN_IE_VERSION_SUBATTR_LEN));
4714 (*ie_len) += (QCN_IE_VERSION_SUBATTR_LEN);
4715
4716 return QDF_STATUS_SUCCESS;
4717}
4718
4719/**
4720 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4721 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304722 * @adapter: Pointer to HDD adapter
4723 * @ie_data: Pointer to Scan IEs buffer
4724 * @ie_len: Length of Scan IEs
4725 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304726 * This API is used to store the default scan ies received from
4727 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
4728 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304729 * Return: 0 on success; error number otherwise
4730 */
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304731static int wlan_hdd_save_default_scan_ies(hdd_context_t *hdd_ctx,
4732 hdd_adapter_t *adapter,
4733 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304734{
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304735 hdd_scaninfo_t *scan_info = &adapter->scan_info;
4736 bool add_qcn_ie = hdd_ctx->config->qcn_ie_support;
4737
4738 if (!scan_info)
4739 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304740
4741 if (scan_info->default_scan_ies) {
4742 qdf_mem_free(scan_info->default_scan_ies);
4743 scan_info->default_scan_ies = NULL;
4744 }
4745
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304746 scan_info->default_scan_ies_len = ie_len;
4747
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304748 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304749 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304750
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304751 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304752 if (!scan_info->default_scan_ies) {
4753 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304754 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304755 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304756
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304757 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
4758 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304759
4760 /* Add QCN IE if g_qcn_ie_support INI is enabled */
4761 if (add_qcn_ie)
4762 wlan_hdd_add_qcn_ie(scan_info->default_scan_ies,
4763 &(scan_info->default_scan_ies_len));
4764
4765 hdd_debug("Saved default scan IE:");
4766 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
4767 (uint8_t *) scan_info->default_scan_ies,
4768 scan_info->default_scan_ies_len);
4769
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304770 return 0;
4771}
4772
4773/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004774 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4775 * vendor command
4776 *
4777 * @wiphy: wiphy device pointer
4778 * @wdev: wireless device pointer
4779 * @data: Vendor command data buffer
4780 * @data_len: Buffer length
4781 *
4782 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4783 *
4784 * Return: Error code.
4785 */
4786static int
4787__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4788 struct wireless_dev *wdev,
4789 const void *data,
4790 int data_len)
4791{
4792 struct net_device *dev = wdev->netdev;
4793 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4794 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4795 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4796 int ret_val = 0;
4797 u32 modulated_dtim;
4798 u16 stats_avg_factor;
4799 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304800 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004801 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004802 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304803 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304804 int attr_len;
4805 int access_policy = 0;
4806 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4807 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304808 uint16_t scan_ie_len = 0;
4809 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304810 struct sir_set_tx_rx_aggregation_size request;
4811 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004812 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004813 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004814 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304815 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08004816 uint32_t ant_div_usrcfg;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304817
Jeff Johnson1f61b612016-02-12 16:28:33 -08004818 ENTER_DEV(dev);
4819
Anurag Chouhan6d760662016-02-20 16:05:43 +05304820 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004821 hdd_err("Command not allowed in FTM mode");
4822 return -EPERM;
4823 }
4824
4825 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304826 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004827 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004828
4829 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4830 data, data_len,
4831 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004832 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004833 return -EINVAL;
4834 }
4835
Krunal Sonie3531942016-04-12 17:43:53 -07004836 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4837 ftm_capab = nla_get_u32(tb[
4838 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4839 hdd_ctx->config->fine_time_meas_cap =
4840 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4841 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304842 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004843 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004844 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4845 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004846 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004847 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4848 hdd_ctx->config->fine_time_meas_cap);
4849 }
4850
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004851 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4852 modulated_dtim = nla_get_u32(
4853 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4854
4855 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4856 adapter->sessionId,
4857 modulated_dtim);
4858
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304859 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 ret_val = -EPERM;
4861 }
4862
Kapil Gupta6213c012016-09-02 19:39:09 +05304863 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4864 qpower = nla_get_u8(
4865 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4866 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4867 ret_val = -EINVAL;
4868 }
4869
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4871 stats_avg_factor = nla_get_u16(
4872 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4873 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4874 adapter->sessionId,
4875 stats_avg_factor);
4876
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304877 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004878 ret_val = -EPERM;
4879 }
4880
4881
4882 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4883 guard_time = nla_get_u32(
4884 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4885 status = sme_configure_guard_time(hdd_ctx->hHal,
4886 adapter->sessionId,
4887 guard_time);
4888
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304889 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004890 ret_val = -EPERM;
4891 }
4892
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304893 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4894 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4895 attr_len = nla_len(
4896 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4897 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004898 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304899 attr_len);
4900 return -EINVAL;
4901 }
4902
4903 nla_memcpy(&vendor_ie,
4904 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4905 attr_len);
4906 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004907 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304908 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304909 }
4910
4911 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4912 access_policy = (int) nla_get_u32(
4913 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4914 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4915 (access_policy >
4916 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004917 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304918 access_policy);
4919 return -EINVAL;
4920 }
4921 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004922 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304923 access_policy);
4924 }
4925
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004926 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4927 retry = nla_get_u8(tb[
4928 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4929 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4930 CFG_NON_AGG_RETRY_MAX : retry;
4931 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4932 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4933 retry, PDEV_CMD);
4934 }
4935
4936 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4937 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4938 retry = retry > CFG_AGG_RETRY_MAX ?
4939 CFG_AGG_RETRY_MAX : retry;
4940
4941 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4942 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4943 CFG_AGG_RETRY_MIN : retry;
4944 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4945 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4946 retry, PDEV_CMD);
4947 }
4948
4949 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4950 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4951 retry = retry > CFG_MGMT_RETRY_MAX ?
4952 CFG_MGMT_RETRY_MAX : retry;
4953 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4954 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4955 retry, PDEV_CMD);
4956 }
4957
4958 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4959 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4960 retry = retry > CFG_CTRL_RETRY_MAX ?
4961 CFG_CTRL_RETRY_MAX : retry;
4962 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4963 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4964 retry, PDEV_CMD);
4965 }
4966
4967 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4968 delay = nla_get_u8(tb[
4969 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4970 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4971 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004972 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004973 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4974 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004975 abs_delay, PDEV_CMD);
4976 }
4977
4978 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4979 abs_delay = nla_get_u8(tb[
4980 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4981 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4982 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4983 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004984 }
4985
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304986 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4987 tx_fail_count = nla_get_u32(
4988 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4989 if (tx_fail_count) {
4990 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4991 adapter->sessionId, tx_fail_count);
4992 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004993 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304994 status);
4995 return -EINVAL;
4996 }
4997 }
4998 }
4999
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305000 if (vendor_ie_present && access_policy_present) {
5001 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
5002 access_policy =
5003 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305004 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305005 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305006 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305007
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005008 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305009 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
5010 adapter->sessionId, &vendor_ie[0],
5011 access_policy);
5012 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005013 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305014 return -EINVAL;
5015 }
5016 }
5017
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305018 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
5019 set_value = nla_get_u8(
5020 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005021 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305022 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
5023 }
5024
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305025 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
5026 scan_ie_len = nla_len(
5027 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005028 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305029 scan_ie_len, adapter->sessionId,
5030 adapter->device_mode);
5031 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
5032 scan_ie = (uint8_t *) nla_data(tb
5033 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305034
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305035 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
5036 scan_ie, scan_ie_len))
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305037 hdd_err("Failed to save default scan IEs");
5038
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305039 if (adapter->device_mode == QDF_STA_MODE) {
5040 status = sme_set_default_scan_ie(hdd_ctx->hHal,
5041 adapter->sessionId, scan_ie,
5042 scan_ie_len);
5043 if (QDF_STATUS_SUCCESS != status)
5044 ret_val = -EPERM;
5045 }
5046 } else
5047 ret_val = -EPERM;
5048 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05305049
5050 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
5051 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
5052 /* if one is specified, both must be specified */
5053 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
5054 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
5055 hdd_err("Both TX and RX MPDU Aggregation required");
5056 return -EINVAL;
5057 }
5058
5059 request.tx_aggregation_size = nla_get_u8(
5060 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
5061 request.rx_aggregation_size = nla_get_u8(
5062 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
5063 request.vdev_id = adapter->sessionId;
5064
5065 if (request.tx_aggregation_size >=
5066 CFG_TX_AGGREGATION_SIZE_MIN &&
5067 request.tx_aggregation_size <=
5068 CFG_TX_AGGREGATION_SIZE_MAX &&
5069 request.rx_aggregation_size >=
5070 CFG_RX_AGGREGATION_SIZE_MIN &&
5071 request.rx_aggregation_size <=
5072 CFG_RX_AGGREGATION_SIZE_MAX) {
5073 qdf_status = wma_set_tx_rx_aggregation_size(&request);
5074 if (qdf_status != QDF_STATUS_SUCCESS) {
5075 hdd_err("failed to set aggr sizes err %d",
5076 qdf_status);
5077 ret_val = -EPERM;
5078 }
5079 } else {
5080 hdd_err("TX %d RX %d MPDU aggr size not in range",
5081 request.tx_aggregation_size,
5082 request.rx_aggregation_size);
5083 ret_val = -EINVAL;
5084 }
5085 }
5086
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305087 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
5088 uint8_t ignore_assoc_disallowed;
5089
5090 ignore_assoc_disallowed
5091 = nla_get_u8(tb[
5092 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005093 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305094 ignore_assoc_disallowed);
5095 if ((ignore_assoc_disallowed <
5096 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
5097 (ignore_assoc_disallowed >
5098 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
5099 return -EPERM;
5100
5101 sme_update_session_param(hdd_ctx->hHal,
5102 adapter->sessionId,
5103 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
5104 ignore_assoc_disallowed);
5105 }
5106
lifeng907edd62017-05-12 10:10:36 +08005107#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
5108 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
5109
5110#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
5111 ((1<<27)|(snr_diff&0x1fff))
5112
5113#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
5114 ((1<<28)|(probe_dwell_time&0x1fff))
5115
5116#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
5117 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
5118 (ack_snr_weight&0xff))
5119
5120 if (tb[ANT_DIV_PROBE_PERIOD] ||
5121 tb[ANT_DIV_STAY_PERIOD]) {
5122
5123 if (!tb[ANT_DIV_PROBE_PERIOD] ||
5124 !tb[ANT_DIV_STAY_PERIOD]) {
5125 hdd_err("Both probe and stay period required");
5126 return -EINVAL;
5127 }
5128
5129 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
5130 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
5131 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
5132 hdd_debug("ant div set period: %x", ant_div_usrcfg);
5133 ret_val = wma_cli_set_command((int)adapter->sessionId,
5134 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5135 ant_div_usrcfg, PDEV_CMD);
5136 if (ret_val) {
5137 hdd_err("Failed to set ant div period");
5138 return ret_val;
5139 }
5140 }
5141
5142 if (tb[ANT_DIV_SNR_DIFF]) {
5143 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
5144 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
5145 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
5146 ret_val = wma_cli_set_command((int)adapter->sessionId,
5147 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5148 ant_div_usrcfg, PDEV_CMD);
5149 if (ret_val) {
5150 hdd_err("Failed to set ant snr diff");
5151 return ret_val;
5152 }
5153 }
5154
5155 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
5156 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
5157 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
5158 hdd_debug("ant div set probe dewll time: %x",
5159 ant_div_usrcfg);
5160 ret_val = wma_cli_set_command((int)adapter->sessionId,
5161 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5162 ant_div_usrcfg, PDEV_CMD);
5163 if (ret_val) {
5164 hdd_err("Failed to set ant div probe dewll time");
5165 return ret_val;
5166 }
5167 }
5168
5169 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5170 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5171 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5172
5173 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5174 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5175 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5176 hdd_err("Mgmt snr, data snr and ack snr weight are required");
5177 return -EINVAL;
5178 }
5179
5180 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
5181 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
5182 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
5183 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
5184 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
5185 ret_val = wma_cli_set_command((int)adapter->sessionId,
5186 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5187 ant_div_usrcfg, PDEV_CMD);
5188 if (ret_val) {
5189 hdd_err("Failed to set ant div weight");
5190 return ret_val;
5191 }
5192 }
5193
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005194 return ret_val;
5195}
5196
5197/**
5198 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
5199 * vendor command
5200 *
5201 * @wiphy: wiphy device pointer
5202 * @wdev: wireless device pointer
5203 * @data: Vendor command data buffer
5204 * @data_len: Buffer length
5205 *
5206 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
5207 *
5208 * Return: EOK or other error codes.
5209 */
5210static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
5211 struct wireless_dev *wdev,
5212 const void *data,
5213 int data_len)
5214{
5215 int ret;
5216
5217 cds_ssr_protect(__func__);
5218 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
5219 data, data_len);
5220 cds_ssr_unprotect(__func__);
5221
5222 return ret;
5223}
5224
5225static const struct
5226nla_policy
5227qca_wlan_vendor_wifi_logger_start_policy
5228[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
5229 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
5230 = {.type = NLA_U32 },
5231 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
5232 = {.type = NLA_U32 },
5233 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
5234 = {.type = NLA_U32 },
5235};
5236
5237/**
5238 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
5239 * or disable the collection of packet statistics from the firmware
5240 * @wiphy: WIPHY structure pointer
5241 * @wdev: Wireless device structure pointer
5242 * @data: Pointer to the data received
5243 * @data_len: Length of the data received
5244 *
5245 * This function enables or disables the collection of packet statistics from
5246 * the firmware
5247 *
5248 * Return: 0 on success and errno on failure
5249 */
5250static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5251 struct wireless_dev *wdev,
5252 const void *data,
5253 int data_len)
5254{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305255 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5257 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
5258 struct sir_wifi_start_log start_log;
5259
Jeff Johnson1f61b612016-02-12 16:28:33 -08005260 ENTER_DEV(wdev->netdev);
5261
Anurag Chouhan6d760662016-02-20 16:05:43 +05305262 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005263 hdd_err("Command not allowed in FTM mode");
5264 return -EPERM;
5265 }
5266
5267 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305268 if (status)
5269 return status;
5270
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05305271 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
5272 hdd_err("Driver Modules are closed, can not start logger");
5273 return -EINVAL;
5274 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275
5276 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
5277 data, data_len,
5278 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005279 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280 return -EINVAL;
5281 }
5282
5283 /* Parse and fetch ring id */
5284 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005285 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005286 return -EINVAL;
5287 }
5288 start_log.ring_id = nla_get_u32(
5289 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005290 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005291
5292 /* Parse and fetch verbose level */
5293 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005294 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005295 return -EINVAL;
5296 }
5297 start_log.verbose_level = nla_get_u32(
5298 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005299 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300
5301 /* Parse and fetch flag */
5302 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005303 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304 return -EINVAL;
5305 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05305306 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005307 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005308 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005309
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305310 /* size is buff size which can be set using iwpriv command*/
5311 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05305312 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305313
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005314 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
5315
5316 if (start_log.ring_id == RING_ID_WAKELOCK) {
5317 /* Start/stop wakelock events */
5318 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
5319 cds_set_wakelock_logging(true);
5320 else
5321 cds_set_wakelock_logging(false);
5322 return 0;
5323 }
5324
5325 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305326 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005327 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 status);
5329 return -EINVAL;
5330 }
5331 return 0;
5332}
5333
5334/**
5335 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
5336 * or disable the collection of packet statistics from the firmware
5337 * @wiphy: WIPHY structure pointer
5338 * @wdev: Wireless device structure pointer
5339 * @data: Pointer to the data received
5340 * @data_len: Length of the data received
5341 *
5342 * This function is used to enable or disable the collection of packet
5343 * statistics from the firmware
5344 *
5345 * Return: 0 on success and errno on failure
5346 */
5347static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5348 struct wireless_dev *wdev,
5349 const void *data,
5350 int data_len)
5351{
5352 int ret = 0;
5353
5354 cds_ssr_protect(__func__);
5355 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5356 wdev, data, data_len);
5357 cds_ssr_unprotect(__func__);
5358
5359 return ret;
5360}
5361
5362static const struct
5363nla_policy
5364qca_wlan_vendor_wifi_logger_get_ring_data_policy
5365[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5366 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5367 = {.type = NLA_U32 },
5368};
5369
5370/**
5371 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5372 * @wiphy: WIPHY structure pointer
5373 * @wdev: Wireless device structure pointer
5374 * @data: Pointer to the data received
5375 * @data_len: Length of the data received
5376 *
5377 * This function is used to flush or retrieve the per packet statistics from
5378 * the driver
5379 *
5380 * Return: 0 on success and errno on failure
5381 */
5382static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5383 struct wireless_dev *wdev,
5384 const void *data,
5385 int data_len)
5386{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305387 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005388 uint32_t ring_id;
5389 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5390 struct nlattr *tb
5391 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5392
Jeff Johnson1f61b612016-02-12 16:28:33 -08005393 ENTER_DEV(wdev->netdev);
5394
Anurag Chouhan6d760662016-02-20 16:05:43 +05305395 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005396 hdd_err("Command not allowed in FTM mode");
5397 return -EPERM;
5398 }
5399
5400 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305401 if (status)
5402 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005403
5404 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5405 data, data_len,
5406 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005407 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408 return -EINVAL;
5409 }
5410
5411 /* Parse and fetch ring id */
5412 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005413 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005414 return -EINVAL;
5415 }
5416
5417 ring_id = nla_get_u32(
5418 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5419
5420 if (ring_id == RING_ID_PER_PACKET_STATS) {
5421 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005422 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305423 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5424 /*
5425 * As part of DRIVER ring ID, flush both driver and fw logs.
5426 * For other Ring ID's driver doesn't have any rings to flush
5427 */
5428 hdd_notice("Bug report triggered by framework");
5429
5430 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5431 WLAN_LOG_INDICATOR_FRAMEWORK,
5432 WLAN_LOG_REASON_CODE_UNUSED,
5433 true, false);
5434 if (QDF_STATUS_SUCCESS != status) {
5435 hdd_err("Failed to trigger bug report");
5436 return -EINVAL;
5437 }
5438 } else {
5439 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5440 WLAN_LOG_INDICATOR_FRAMEWORK,
5441 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005442 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443 return 0;
5444}
5445
5446/**
5447 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5448 * @wiphy: WIPHY structure pointer
5449 * @wdev: Wireless device structure pointer
5450 * @data: Pointer to the data received
5451 * @data_len: Length of the data received
5452 *
5453 * This function is used to flush or retrieve the per packet statistics from
5454 * the driver
5455 *
5456 * Return: 0 on success and errno on failure
5457 */
5458static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5459 struct wireless_dev *wdev,
5460 const void *data,
5461 int data_len)
5462{
5463 int ret = 0;
5464
5465 cds_ssr_protect(__func__);
5466 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5467 wdev, data, data_len);
5468 cds_ssr_unprotect(__func__);
5469
5470 return ret;
5471}
5472
5473#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5474/**
5475 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5476 * @hdd_ctx: HDD context
5477 * @request_id: [input] request id
5478 * @pattern_id: [output] pattern id
5479 *
5480 * This function loops through request id to pattern id array
5481 * if the slot is available, store the request id and return pattern id
5482 * if entry exists, return the pattern id
5483 *
5484 * Return: 0 on success and errno on failure
5485 */
5486static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5487 uint32_t request_id,
5488 uint8_t *pattern_id)
5489{
5490 uint32_t i;
5491
5492 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5493 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5494 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5495 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5496 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5497 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5498 return 0;
5499 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5500 request_id) {
5501 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5502 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5503 return 0;
5504 }
5505 }
5506 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5507 return -EINVAL;
5508}
5509
5510/**
5511 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5512 * @hdd_ctx: HDD context
5513 * @request_id: [input] request id
5514 * @pattern_id: [output] pattern id
5515 *
5516 * This function loops through request id to pattern id array
5517 * reset request id to 0 (slot available again) and
5518 * return pattern id
5519 *
5520 * Return: 0 on success and errno on failure
5521 */
5522static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5523 uint32_t request_id,
5524 uint8_t *pattern_id)
5525{
5526 uint32_t i;
5527
5528 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5529 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5530 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5531 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5532 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5533 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5534 return 0;
5535 }
5536 }
5537 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5538 return -EINVAL;
5539}
5540
5541
5542/*
5543 * define short names for the global vendor params
5544 * used by __wlan_hdd_cfg80211_offloaded_packets()
5545 */
5546#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5547#define PARAM_REQUEST_ID \
5548 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5549#define PARAM_CONTROL \
5550 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5551#define PARAM_IP_PACKET \
5552 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5553#define PARAM_SRC_MAC_ADDR \
5554 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5555#define PARAM_DST_MAC_ADDR \
5556 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5557#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5558
5559/**
5560 * wlan_hdd_add_tx_ptrn() - add tx pattern
5561 * @adapter: adapter pointer
5562 * @hdd_ctx: hdd context
5563 * @tb: nl attributes
5564 *
5565 * This function reads the NL attributes and forms a AddTxPtrn message
5566 * posts it to SME.
5567 *
5568 */
5569static int
5570wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5571 struct nlattr **tb)
5572{
5573 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305574 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 uint32_t request_id, ret, len;
5576 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305577 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005578 uint16_t eth_type = htons(ETH_P_IP);
5579
5580 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005581 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 return -ENOTSUPP;
5583 }
5584
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305585 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005586 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005587 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005588 return -ENOMEM;
5589 }
5590
5591 /* Parse and fetch request Id */
5592 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005593 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005594 goto fail;
5595 }
5596
5597 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5598 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005599 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005600 return -EINVAL;
5601 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005602 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005603
5604 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005605 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005606 goto fail;
5607 }
5608 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005609 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005610 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005611 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005612 goto fail;
5613 }
5614
5615 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005616 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005617 goto fail;
5618 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005619 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305620 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005621 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005622 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005623
Anurag Chouhanc5548422016-02-24 18:33:27 +05305624 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005625 &adapter->macAddressCurrent)) {
5626 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005627 goto fail;
5628 }
5629
5630 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005631 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632 goto fail;
5633 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305634 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005635 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005636 MAC_ADDR_ARRAY(dst_addr.bytes));
5637
5638 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005639 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005640 goto fail;
5641 }
5642 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005643 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005644
5645 if (add_req->ucPtrnSize < 0 ||
5646 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5647 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005648 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005649 add_req->ucPtrnSize);
5650 goto fail;
5651 }
5652
5653 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305654 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305655 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305656 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305657 QDF_MAC_ADDR_SIZE);
5658 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305659 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660 len += 2;
5661
5662 /*
5663 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5664 * ------------------------------------------------------------
5665 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5666 * ------------------------------------------------------------
5667 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305668 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005669 nla_data(tb[PARAM_IP_PACKET]),
5670 add_req->ucPtrnSize);
5671 add_req->ucPtrnSize += len;
5672
5673 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5674 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005675 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005676 goto fail;
5677 }
5678 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005679 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005680
5681 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305682 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005683 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005684 goto fail;
5685 }
5686
5687 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305688 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005689 return 0;
5690
5691fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305692 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005693 return -EINVAL;
5694}
5695
5696/**
5697 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5698 * @adapter: adapter pointer
5699 * @hdd_ctx: hdd context
5700 * @tb: nl attributes
5701 *
5702 * This function reads the NL attributes and forms a DelTxPtrn message
5703 * posts it to SME.
5704 *
5705 */
5706static int
5707wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5708 struct nlattr **tb)
5709{
5710 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305711 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005712 uint32_t request_id, ret;
5713 uint8_t pattern_id = 0;
5714
5715 /* Parse and fetch request Id */
5716 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005717 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005718 return -EINVAL;
5719 }
5720 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5721 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005722 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005723 return -EINVAL;
5724 }
5725
5726 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5727 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005728 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005729 return -EINVAL;
5730 }
5731
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305732 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005734 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735 return -ENOMEM;
5736 }
5737
Anurag Chouhanc5548422016-02-24 18:33:27 +05305738 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005739 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005740 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005741 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005742 request_id, del_req->ucPtrnId);
5743
5744 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305745 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005746 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005747 goto fail;
5748 }
5749
5750 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305751 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005752 return 0;
5753
5754fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305755 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005756 return -EINVAL;
5757}
5758
5759
5760/**
5761 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5762 * @wiphy: Pointer to wireless phy
5763 * @wdev: Pointer to wireless device
5764 * @data: Pointer to data
5765 * @data_len: Data length
5766 *
5767 * Return: 0 on success, negative errno on failure
5768 */
5769static int
5770__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5771 struct wireless_dev *wdev,
5772 const void *data,
5773 int data_len)
5774{
5775 struct net_device *dev = wdev->netdev;
5776 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5777 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5778 struct nlattr *tb[PARAM_MAX + 1];
5779 uint8_t control;
5780 int ret;
5781 static const struct nla_policy policy[PARAM_MAX + 1] = {
5782 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5783 [PARAM_CONTROL] = { .type = NLA_U32 },
5784 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305785 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005786 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305787 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005788 [PARAM_PERIOD] = { .type = NLA_U32 },
5789 };
5790
Jeff Johnson1f61b612016-02-12 16:28:33 -08005791 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005792
Anurag Chouhan6d760662016-02-20 16:05:43 +05305793 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794 hdd_err("Command not allowed in FTM mode");
5795 return -EPERM;
5796 }
5797
5798 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305799 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005800 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005801
5802 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005803 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005804 return -ENOTSUPP;
5805 }
5806
5807 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005808 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809 return -EINVAL;
5810 }
5811
5812 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005813 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005814 return -EINVAL;
5815 }
5816 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005817 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005818
5819 if (control == WLAN_START_OFFLOADED_PACKETS)
5820 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005821 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005822 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005823
5824 hdd_err("Invalid control: %d", control);
5825
5826 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005827}
5828
5829/*
5830 * done with short names for the global vendor params
5831 * used by __wlan_hdd_cfg80211_offloaded_packets()
5832 */
5833#undef PARAM_MAX
5834#undef PARAM_REQUEST_ID
5835#undef PARAM_CONTROL
5836#undef PARAM_IP_PACKET
5837#undef PARAM_SRC_MAC_ADDR
5838#undef PARAM_DST_MAC_ADDR
5839#undef PARAM_PERIOD
5840
5841/**
5842 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5843 * @wiphy: wiphy structure pointer
5844 * @wdev: Wireless device structure pointer
5845 * @data: Pointer to the data received
5846 * @data_len: Length of @data
5847 *
5848 * Return: 0 on success; errno on failure
5849 */
5850static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5851 struct wireless_dev *wdev,
5852 const void *data,
5853 int data_len)
5854{
5855 int ret = 0;
5856
5857 cds_ssr_protect(__func__);
5858 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5859 wdev, data, data_len);
5860 cds_ssr_unprotect(__func__);
5861
5862 return ret;
5863}
5864#endif
5865
5866/*
5867 * define short names for the global vendor params
5868 * used by __wlan_hdd_cfg80211_monitor_rssi()
5869 */
5870#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5871#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5872#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5873#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5874#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5875
5876/**
5877 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5878 * @wiphy: Pointer to wireless phy
5879 * @wdev: Pointer to wireless device
5880 * @data: Pointer to data
5881 * @data_len: Data length
5882 *
5883 * Return: 0 on success, negative errno on failure
5884 */
5885static int
5886__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5887 struct wireless_dev *wdev,
5888 const void *data,
5889 int data_len)
5890{
5891 struct net_device *dev = wdev->netdev;
5892 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5893 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5894 struct nlattr *tb[PARAM_MAX + 1];
5895 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305896 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005897 int ret;
5898 uint32_t control;
5899 static const struct nla_policy policy[PARAM_MAX + 1] = {
5900 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5901 [PARAM_CONTROL] = { .type = NLA_U32 },
5902 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5903 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5904 };
5905
Jeff Johnson1f61b612016-02-12 16:28:33 -08005906 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005907
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305908 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5909 hdd_err("invalid session id: %d", adapter->sessionId);
5910 return -EINVAL;
5911 }
5912
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005913 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305914 if (ret)
5915 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005916
5917 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005918 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919 return -ENOTSUPP;
5920 }
5921
5922 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005923 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005924 return -EINVAL;
5925 }
5926
5927 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005928 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929 return -EINVAL;
5930 }
5931
5932 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005933 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005934 return -EINVAL;
5935 }
5936
5937 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5938 req.session_id = adapter->sessionId;
5939 control = nla_get_u32(tb[PARAM_CONTROL]);
5940
5941 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5942 req.control = true;
5943 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005944 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005945 return -EINVAL;
5946 }
5947
5948 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005949 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005950 return -EINVAL;
5951 }
5952
5953 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5954 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5955
5956 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005957 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005958 req.min_rssi, req.max_rssi);
5959 return -EINVAL;
5960 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005961 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962 req.min_rssi, req.max_rssi);
5963
5964 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5965 req.control = false;
5966 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005967 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005968 return -EINVAL;
5969 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005970 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005971 req.request_id, req.session_id, req.control);
5972
5973 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305974 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005975 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005976 return -EINVAL;
5977 }
5978
5979 return 0;
5980}
5981
5982/*
5983 * done with short names for the global vendor params
5984 * used by __wlan_hdd_cfg80211_monitor_rssi()
5985 */
5986#undef PARAM_MAX
5987#undef PARAM_CONTROL
5988#undef PARAM_REQUEST_ID
5989#undef PARAM_MAX_RSSI
5990#undef PARAM_MIN_RSSI
5991
5992/**
5993 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5994 * @wiphy: wiphy structure pointer
5995 * @wdev: Wireless device structure pointer
5996 * @data: Pointer to the data received
5997 * @data_len: Length of @data
5998 *
5999 * Return: 0 on success; errno on failure
6000 */
6001static int
6002wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
6003 const void *data, int data_len)
6004{
6005 int ret;
6006
6007 cds_ssr_protect(__func__);
6008 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
6009 cds_ssr_unprotect(__func__);
6010
6011 return ret;
6012}
6013
6014/**
6015 * hdd_rssi_threshold_breached() - rssi breached NL event
6016 * @hddctx: HDD context
6017 * @data: rssi breached event data
6018 *
6019 * This function reads the rssi breached event %data and fill in the skb with
6020 * NL attributes and send up the NL event.
6021 *
6022 * Return: none
6023 */
6024void hdd_rssi_threshold_breached(void *hddctx,
6025 struct rssi_breach_event *data)
6026{
6027 hdd_context_t *hdd_ctx = hddctx;
6028 struct sk_buff *skb;
6029
6030 ENTER();
6031
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306032 if (wlan_hdd_validate_context(hdd_ctx))
6033 return;
6034 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006035 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006036 return;
6037 }
6038
6039 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
6040 NULL,
6041 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
6042 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
6043 GFP_KERNEL);
6044
6045 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006046 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006047 return;
6048 }
6049
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006050 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006051 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006052 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006053 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
6054
6055 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
6056 data->request_id) ||
6057 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
6058 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
6059 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
6060 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006061 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006062 goto fail;
6063 }
6064
6065 cfg80211_vendor_event(skb, GFP_KERNEL);
6066 return;
6067
6068fail:
6069 kfree_skb(skb);
6070 return;
6071}
6072
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306073static const struct nla_policy
6074ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
6075 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
6076};
6077
6078/**
6079 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
6080 * @wiphy: Pointer to wireless phy
6081 * @wdev: Pointer to wireless device
6082 * @data: Pointer to data
6083 * @data_len: Length of @data
6084 *
6085 * Return: 0 on success, negative errno on failure
6086 */
6087static int
6088__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
6089 struct wireless_dev *wdev,
6090 const void *data, int data_len)
6091{
6092 int status;
6093 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
6094 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07006095 struct net_device *dev = wdev->netdev;
6096 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306097
6098 ENTER_DEV(wdev->netdev);
6099
6100 status = wlan_hdd_validate_context(pHddCtx);
6101 if (0 != status)
6102 return status;
6103 if (!pHddCtx->config->fhostNSOffload) {
6104 hdd_err("ND Offload not supported");
6105 return -EINVAL;
6106 }
6107
6108 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
6109 (struct nlattr *)data,
6110 data_len, ns_offload_set_policy)) {
6111 hdd_err("nla_parse failed");
6112 return -EINVAL;
6113 }
6114
6115 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
6116 hdd_err("ND Offload flag attribute not present");
6117 return -EINVAL;
6118 }
6119
6120 pHddCtx->ns_offload_enable =
6121 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
6122
Dustin Brownd8279d22016-09-07 14:52:57 -07006123 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05306124 if (pHddCtx->ns_offload_enable)
6125 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
6126 else
6127 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07006128
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306129 return 0;
6130}
6131
6132/**
6133 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
6134 * @wiphy: pointer to wireless wiphy structure.
6135 * @wdev: pointer to wireless_dev structure.
6136 * @data: Pointer to the data to be passed via vendor interface
6137 * @data_len:Length of the data to be passed
6138 *
6139 * Return: Return the Success or Failure code.
6140 */
6141static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
6142 struct wireless_dev *wdev,
6143 const void *data, int data_len)
6144{
6145 int ret;
6146
6147 cds_ssr_protect(__func__);
6148 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
6149 cds_ssr_unprotect(__func__);
6150
6151 return ret;
6152}
6153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006154/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
6155 * @wiphy: Pointer to wireless phy
6156 * @wdev: Pointer to wireless device
6157 * @data: Pointer to data
6158 * @data_len: Data length
6159 *
6160 * This function return the preferred frequency list generated by the policy
6161 * manager.
6162 *
6163 * Return: success or failure code
6164 */
6165static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6166 struct wireless_dev
6167 *wdev, const void *data,
6168 int data_len)
6169{
6170 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6171 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306172 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306173 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306175 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006176 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006177 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6178 struct sk_buff *reply_skb;
6179
Jeff Johnson1f61b612016-02-12 16:28:33 -08006180 ENTER_DEV(wdev->netdev);
6181
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006182 ret = wlan_hdd_validate_context(hdd_ctx);
6183 if (ret)
6184 return -EINVAL;
6185
6186 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
6187 data, data_len, NULL)) {
6188 hdd_err("Invalid ATTR");
6189 return -EINVAL;
6190 }
6191
6192 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
6193 hdd_err("attr interface type failed");
6194 return -EINVAL;
6195 }
6196
6197 intf_mode = nla_get_u32(tb
6198 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
6199
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006200 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006201 hdd_err("Invalid interface type");
6202 return -EINVAL;
6203 }
6204
6205 hdd_debug("Userspace requested pref freq list");
6206
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006207 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
6208 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05306209 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306210 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006211 hdd_err("Get pcl failed");
6212 return -EINVAL;
6213 }
6214
6215 /* convert channel number to frequency */
6216 for (i = 0; i < pcl_len; i++) {
6217 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
6218 freq_list[i] =
6219 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006220 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006221 else
6222 freq_list[i] =
6223 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006224 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006225 }
6226
6227 /* send the freq_list back to supplicant */
6228 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
6229 sizeof(u32) *
6230 pcl_len +
6231 NLMSG_HDRLEN);
6232
6233 if (!reply_skb) {
6234 hdd_err("Allocate reply_skb failed");
6235 return -EINVAL;
6236 }
6237
6238 if (nla_put_u32(reply_skb,
6239 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
6240 intf_mode) ||
6241 nla_put(reply_skb,
6242 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
6243 sizeof(uint32_t) * pcl_len,
6244 freq_list)) {
6245 hdd_err("nla put fail");
6246 kfree_skb(reply_skb);
6247 return -EINVAL;
6248 }
6249
6250 return cfg80211_vendor_cmd_reply(reply_skb);
6251}
6252
6253/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
6254 * @wiphy: Pointer to wireless phy
6255 * @wdev: Pointer to wireless device
6256 * @data: Pointer to data
6257 * @data_len: Data length
6258 *
6259 * This function return the preferred frequency list generated by the policy
6260 * manager.
6261 *
6262 * Return: success or failure code
6263 */
6264static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6265 struct wireless_dev
6266 *wdev, const void *data,
6267 int data_len)
6268{
6269 int ret = 0;
6270
6271 cds_ssr_protect(__func__);
6272 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
6273 data, data_len);
6274 cds_ssr_unprotect(__func__);
6275
6276 return ret;
6277}
6278
6279/**
6280 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6281 * @wiphy: Pointer to wireless phy
6282 * @wdev: Pointer to wireless device
6283 * @data: Pointer to data
6284 * @data_len: Data length
6285 *
6286 * Return: 0 on success, negative errno on failure
6287 */
6288static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6289 struct wireless_dev *wdev,
6290 const void *data,
6291 int data_len)
6292{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05306293 struct net_device *ndev = wdev->netdev;
6294 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006295 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6296 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006297 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006298 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6299 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006300
Jeff Johnson1f61b612016-02-12 16:28:33 -08006301 ENTER_DEV(ndev);
6302
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006303 ret = wlan_hdd_validate_context(hdd_ctx);
6304 if (ret)
6305 return ret;
6306
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006307 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
6308 data, data_len, NULL)) {
6309 hdd_err("Invalid ATTR");
6310 return -EINVAL;
6311 }
6312
6313 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
6314 hdd_err("attr interface type failed");
6315 return -EINVAL;
6316 }
6317
6318 intf_mode = nla_get_u32(tb
6319 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
6320
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006321 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006322 hdd_err("Invalid interface type");
6323 return -EINVAL;
6324 }
6325
6326 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
6327 hdd_err("attr probable freq failed");
6328 return -EINVAL;
6329 }
6330
6331 channel_hint = cds_freq_to_chan(nla_get_u32(tb
6332 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
6333
6334 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006335 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006336 channel_hint, HW_MODE_20_MHZ)) {
6337 hdd_err("Set channel hint failed due to concurrency check");
6338 return -EINVAL;
6339 }
6340
Krunal Soni09e55032016-06-07 10:06:55 -07006341 if (0 != wlan_hdd_check_remain_on_channel(adapter))
6342 hdd_warn("Remain On Channel Pending");
6343
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006344 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006345 if (!QDF_IS_STATUS_SUCCESS(ret))
6346 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006347
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006348 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
6349 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07006350 SIR_UPDATE_REASON_SET_OPER_CHAN);
6351 if (QDF_STATUS_E_FAILURE == ret) {
6352 /* return in the failure case */
6353 hdd_err("ERROR: connections update failed!!");
6354 return -EINVAL;
6355 }
6356
6357 if (QDF_STATUS_SUCCESS == ret) {
6358 /*
6359 * Success is the only case for which we expect hw mode
6360 * change to take place, hence we need to wait.
6361 * For any other return value it should be a pass
6362 * through
6363 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006364 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006365 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6366 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006367 return -EINVAL;
6368 }
6369
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006370 }
6371
6372 return 0;
6373}
6374
6375/**
6376 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6377 * @wiphy: Pointer to wireless phy
6378 * @wdev: Pointer to wireless device
6379 * @data: Pointer to data
6380 * @data_len: Data length
6381 *
6382 * Return: 0 on success, negative errno on failure
6383 */
6384static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6385 struct wireless_dev *wdev,
6386 const void *data,
6387 int data_len)
6388{
6389 int ret = 0;
6390
6391 cds_ssr_protect(__func__);
6392 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6393 data, data_len);
6394 cds_ssr_unprotect(__func__);
6395
6396 return ret;
6397}
6398
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306399static const struct
6400nla_policy
6401qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6402 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6403};
6404
6405/**
6406 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6407 * @wiphy: WIPHY structure pointer
6408 * @wdev: Wireless device structure pointer
6409 * @data: Pointer to the data received
6410 * @data_len: Length of the data received
6411 *
6412 * This function is used to get link properties like nss, rate flags and
6413 * operating frequency for the active connection with the given peer.
6414 *
6415 * Return: 0 on success and errno on failure
6416 */
6417static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6418 struct wireless_dev *wdev,
6419 const void *data,
6420 int data_len)
6421{
6422 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6423 struct net_device *dev = wdev->netdev;
6424 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6425 hdd_station_ctx_t *hdd_sta_ctx;
6426 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306427 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306428 uint32_t sta_id;
6429 struct sk_buff *reply_skb;
6430 uint32_t rate_flags = 0;
6431 uint8_t nss;
6432 uint8_t final_rate_flags = 0;
6433 uint32_t freq;
6434
Jeff Johnson1f61b612016-02-12 16:28:33 -08006435 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306436
Anurag Chouhan6d760662016-02-20 16:05:43 +05306437 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306438 hdd_err("Command not allowed in FTM mode");
6439 return -EPERM;
6440 }
6441
6442 if (0 != wlan_hdd_validate_context(hdd_ctx))
6443 return -EINVAL;
6444
6445 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6446 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006447 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306448 return -EINVAL;
6449 }
6450
6451 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006452 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306453 adapter->device_mode);
6454 return -EINVAL;
6455 }
6456
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306457 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306458 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006459 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306460 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6461
Krunal Sonib4326f22016-03-10 13:05:51 -08006462 if (adapter->device_mode == QDF_STA_MODE ||
6463 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306464 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6465 if ((hdd_sta_ctx->conn_info.connState !=
6466 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306467 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306468 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006469 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306470 MAC_ADDR_ARRAY(peer_mac));
6471 return -EINVAL;
6472 }
6473
6474 nss = hdd_sta_ctx->conn_info.nss;
6475 freq = cds_chan_to_freq(
6476 hdd_sta_ctx->conn_info.operationChannel);
6477 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006478 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6479 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306480
6481 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6482 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306483 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306484 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306485 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306486 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306487 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306488 break;
6489 }
6490
6491 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006492 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306493 MAC_ADDR_ARRAY(peer_mac));
6494 return -EINVAL;
6495 }
6496
6497 nss = adapter->aStaInfo[sta_id].nss;
6498 freq = cds_chan_to_freq(
6499 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6500 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6501 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006502 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306503 MAC_ADDR_ARRAY(peer_mac));
6504 return -EINVAL;
6505 }
6506
6507 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6508 if (rate_flags & eHAL_TX_RATE_VHT80) {
6509 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006510#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306511 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006512#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306513 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6514 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006515#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306516 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006517#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306518 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6519 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6520 } else if (rate_flags &
6521 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6522 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006523#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306524 if (rate_flags & eHAL_TX_RATE_HT40)
6525 final_rate_flags |=
6526 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006527#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306528 }
6529
6530 if (rate_flags & eHAL_TX_RATE_SGI) {
6531 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6532 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6533 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6534 }
6535 }
6536
6537 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6538 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6539
6540 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006541 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306542 return -EINVAL;
6543 }
6544
6545 if (nla_put_u8(reply_skb,
6546 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6547 nss) ||
6548 nla_put_u8(reply_skb,
6549 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6550 final_rate_flags) ||
6551 nla_put_u32(reply_skb,
6552 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6553 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006554 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306555 kfree_skb(reply_skb);
6556 return -EINVAL;
6557 }
6558
6559 return cfg80211_vendor_cmd_reply(reply_skb);
6560}
6561
6562/**
6563 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6564 * properties.
6565 * @wiphy: WIPHY structure pointer
6566 * @wdev: Wireless device structure pointer
6567 * @data: Pointer to the data received
6568 * @data_len: Length of the data received
6569 *
6570 * This function is used to get link properties like nss, rate flags and
6571 * operating frequency for the active connection with the given peer.
6572 *
6573 * Return: 0 on success and errno on failure
6574 */
6575static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6576 struct wireless_dev *wdev,
6577 const void *data,
6578 int data_len)
6579{
6580 int ret = 0;
6581
6582 cds_ssr_protect(__func__);
6583 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6584 wdev, data, data_len);
6585 cds_ssr_unprotect(__func__);
6586
6587 return ret;
6588}
6589
Peng Xu278d0122015-09-24 16:34:17 -07006590static const struct
6591nla_policy
6592qca_wlan_vendor_ota_test_policy
6593[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6594 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6595};
6596
6597/**
6598 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6599 * @wiphy: Pointer to wireless phy
6600 * @wdev: Pointer to wireless device
6601 * @data: Pointer to data
6602 * @data_len: Data length
6603 *
6604 * Return: 0 on success, negative errno on failure
6605 */
6606static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6607 struct wireless_dev *wdev,
6608 const void *data,
6609 int data_len)
6610{
6611 struct net_device *dev = wdev->netdev;
6612 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6613 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6614 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6615 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6616 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306617 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006618 uint32_t current_roam_state;
6619
Jeff Johnson1f61b612016-02-12 16:28:33 -08006620 ENTER_DEV(dev);
6621
Anurag Chouhan6d760662016-02-20 16:05:43 +05306622 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006623 hdd_err("Command not allowed in FTM mode");
6624 return -EPERM;
6625 }
6626
6627 if (0 != wlan_hdd_validate_context(hdd_ctx))
6628 return -EINVAL;
6629
6630 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6631 data, data_len,
6632 qca_wlan_vendor_ota_test_policy)) {
6633 hdd_err("invalid attr");
6634 return -EINVAL;
6635 }
6636
6637 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6638 hdd_err("attr ota test failed");
6639 return -EINVAL;
6640 }
6641
6642 ota_enable = nla_get_u8(
6643 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6644
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006645 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006646 if (ota_enable != 1) {
6647 hdd_err("Invalid value, only enable test mode is supported!");
6648 return -EINVAL;
6649 }
6650
6651 current_roam_state =
6652 sme_get_current_roam_state(hal, adapter->sessionId);
6653 status = sme_stop_roaming(hal, adapter->sessionId,
6654 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306655 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006656 hdd_err("Enable/Disable roaming failed");
6657 return -EINVAL;
6658 }
6659
6660 status = sme_ps_enable_disable(hal, adapter->sessionId,
6661 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306662 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006663 hdd_err("Enable/Disable power save failed");
6664 /* restore previous roaming setting */
6665 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6666 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6667 status = sme_start_roaming(hal, adapter->sessionId,
6668 eCsrHddIssued);
6669 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6670 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6671 status = sme_stop_roaming(hal, adapter->sessionId,
6672 eCsrHddIssued);
6673
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306674 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006675 hdd_err("Restoring roaming state failed");
6676
6677 return -EINVAL;
6678 }
6679
6680
6681 return 0;
6682}
6683
6684/**
6685 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6686 * @wiphy: Pointer to wireless phy
6687 * @wdev: Pointer to wireless device
6688 * @data: Pointer to data
6689 * @data_len: Data length
6690 *
6691 * Return: 0 on success, negative errno on failure
6692 */
6693static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6694 struct wireless_dev *wdev,
6695 const void *data,
6696 int data_len)
6697{
6698 int ret = 0;
6699
6700 cds_ssr_protect(__func__);
6701 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6702 cds_ssr_unprotect(__func__);
6703
6704 return ret;
6705}
6706
Peng Xu4d67c8f2015-10-16 16:02:26 -07006707/**
6708 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6709 * @wiphy: Pointer to wireless phy
6710 * @wdev: Pointer to wireless device
6711 * @data: Pointer to data
6712 * @data_len: Data length
6713 *
6714 * Return: 0 on success, negative errno on failure
6715 */
6716static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6717 struct wireless_dev *wdev,
6718 const void *data,
6719 int data_len)
6720{
6721 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6722 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006723 hdd_adapter_t *adapter;
6724 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006725 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6726 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006727 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006728
Jeff Johnson1f61b612016-02-12 16:28:33 -08006729 ENTER_DEV(dev);
6730
Peng Xu4d67c8f2015-10-16 16:02:26 -07006731 ret = wlan_hdd_validate_context(hdd_ctx);
6732 if (ret)
6733 return ret;
6734
6735 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6736
6737 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6738 data, data_len, NULL)) {
6739 hdd_err("Invalid ATTR");
6740 return -EINVAL;
6741 }
6742
6743 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6744 hdd_err("attr tx power scale failed");
6745 return -EINVAL;
6746 }
6747
6748 scale_value = nla_get_u8(tb
6749 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6750
6751 if (scale_value > MAX_TXPOWER_SCALE) {
6752 hdd_err("Invalid tx power scale level");
6753 return -EINVAL;
6754 }
6755
Peng Xu62c8c432016-05-09 15:23:02 -07006756 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006757
Peng Xu62c8c432016-05-09 15:23:02 -07006758 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006759 hdd_err("Set tx power scale failed");
6760 return -EINVAL;
6761 }
6762
6763 return 0;
6764}
6765
6766/**
6767 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6768 * @wiphy: Pointer to wireless phy
6769 * @wdev: Pointer to wireless device
6770 * @data: Pointer to data
6771 * @data_len: Data length
6772 *
6773 * Return: 0 on success, negative errno on failure
6774 */
6775static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6776 struct wireless_dev *wdev,
6777 const void *data,
6778 int data_len)
6779{
Peng Xu62c8c432016-05-09 15:23:02 -07006780 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006781
6782 cds_ssr_protect(__func__);
6783 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6784 data, data_len);
6785 cds_ssr_unprotect(__func__);
6786
6787 return ret;
6788}
6789
6790/**
6791 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6792 * @wiphy: Pointer to wireless phy
6793 * @wdev: Pointer to wireless device
6794 * @data: Pointer to data
6795 * @data_len: Data length
6796 *
6797 * Return: 0 on success, negative errno on failure
6798 */
6799static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6800 struct wireless_dev *wdev,
6801 const void *data,
6802 int data_len)
6803{
6804 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6805 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006806 hdd_adapter_t *adapter;
6807 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006808 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6809 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006810 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006811
Jeff Johnson1f61b612016-02-12 16:28:33 -08006812 ENTER_DEV(dev);
6813
Peng Xu4d67c8f2015-10-16 16:02:26 -07006814 ret = wlan_hdd_validate_context(hdd_ctx);
6815 if (ret)
6816 return ret;
6817
6818 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6819
6820 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6821 data, data_len, NULL)) {
6822 hdd_err("Invalid ATTR");
6823 return -EINVAL;
6824 }
6825
6826 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6827 hdd_err("attr tx power decrease db value failed");
6828 return -EINVAL;
6829 }
6830
6831 scale_value = nla_get_u8(tb
6832 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6833
Peng Xu62c8c432016-05-09 15:23:02 -07006834 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6835 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006836
Peng Xu62c8c432016-05-09 15:23:02 -07006837 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006838 hdd_err("Set tx power decrease db failed");
6839 return -EINVAL;
6840 }
6841
6842 return 0;
6843}
6844
6845/**
6846 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6847 * @wiphy: Pointer to wireless phy
6848 * @wdev: Pointer to wireless device
6849 * @data: Pointer to data
6850 * @data_len: Data length
6851 *
6852 * Return: 0 on success, negative errno on failure
6853 */
6854static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6855 struct wireless_dev *wdev,
6856 const void *data,
6857 int data_len)
6858{
Peng Xu62c8c432016-05-09 15:23:02 -07006859 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006860
6861 cds_ssr_protect(__func__);
6862 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6863 data, data_len);
6864 cds_ssr_unprotect(__func__);
6865
6866 return ret;
6867}
Peng Xu8fdaa492016-06-22 10:20:47 -07006868
6869/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306870 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6871 * @wiphy: Pointer to wireless phy
6872 * @wdev: Pointer to wireless device
6873 * @data: Pointer to data
6874 * @data_len: Data length
6875 *
6876 * Processes the conditional channel switch request and invokes the helper
6877 * APIs to process the channel switch request.
6878 *
6879 * Return: 0 on success, negative errno on failure
6880 */
6881static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6882 struct wireless_dev *wdev,
6883 const void *data,
6884 int data_len)
6885{
6886 int ret;
6887 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6888 struct net_device *dev = wdev->netdev;
6889 hdd_adapter_t *adapter;
6890 struct nlattr
6891 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6892 uint32_t freq_len, i;
6893 uint32_t *freq;
6894 uint8_t chans[QDF_MAX_NUM_CHAN];
6895
6896 ENTER_DEV(dev);
6897
6898 ret = wlan_hdd_validate_context(hdd_ctx);
6899 if (ret)
6900 return ret;
6901
6902 if (!hdd_ctx->config->enableDFSMasterCap) {
6903 hdd_err("DFS master capability is not present in the driver");
6904 return -EINVAL;
6905 }
6906
6907 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6908 hdd_err("Command not allowed in FTM mode");
6909 return -EPERM;
6910 }
6911
6912 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6913 if (adapter->device_mode != QDF_SAP_MODE) {
6914 hdd_err("Invalid device mode %d", adapter->device_mode);
6915 return -EINVAL;
6916 }
6917
6918 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6919 data, data_len, NULL)) {
6920 hdd_err("Invalid ATTR");
6921 return -EINVAL;
6922 }
6923
6924 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6925 hdd_err("Frequency list is missing");
6926 return -EINVAL;
6927 }
6928
6929 freq_len = nla_len(
6930 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6931 sizeof(uint32_t);
6932
6933 if (freq_len > QDF_MAX_NUM_CHAN) {
6934 hdd_err("insufficient space to hold channels");
6935 return -ENOMEM;
6936 }
6937
6938 hdd_debug("freq_len=%d", freq_len);
6939
6940 freq = nla_data(
6941 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6942
6943
6944 for (i = 0; i < freq_len; i++) {
6945 if (freq[i] == 0)
6946 chans[i] = 0;
6947 else
6948 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6949
6950 hdd_debug("freq[%d]=%d", i, freq[i]);
6951 }
6952
6953 /*
6954 * The input frequency list from user space is designed to be a
6955 * priority based frequency list. This is only to accommodate any
6956 * future request. But, current requirement is only to perform CAC
6957 * on a single channel. So, the first entry from the list is picked.
6958 *
6959 * If channel is zero, any channel in the available outdoor regulatory
6960 * domain will be selected.
6961 */
6962 ret = wlan_hdd_request_pre_cac(chans[0]);
6963 if (ret) {
6964 hdd_err("pre cac request failed with reason:%d", ret);
6965 return ret;
6966 }
6967
6968 return 0;
6969}
6970
6971/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006972 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6973 * @wiphy: Pointer to wireless phy
6974 * @wdev: Pointer to wireless device
6975 * @data: Pointer to data
6976 * @data_len: Data length
6977 *
6978 * This function is to process the p2p listen offload start vendor
6979 * command. It parses the input parameters and invoke WMA API to
6980 * send the command to firmware.
6981 *
6982 * Return: 0 on success, negative errno on failure
6983 */
6984static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6985 struct wireless_dev *wdev,
6986 const void *data,
6987 int data_len)
6988{
6989 int ret;
6990 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6991 struct net_device *dev = wdev->netdev;
6992 hdd_adapter_t *adapter;
6993 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6994 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006995
6996 ENTER_DEV(dev);
6997
6998 ret = wlan_hdd_validate_context(hdd_ctx);
6999 if (ret)
7000 return ret;
7001
7002 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7003 hdd_err("Command not allowed in FTM mode");
7004 return -EPERM;
7005 }
7006
7007 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7008 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
7009 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
7010 (adapter->device_mode != QDF_P2P_GO_MODE)) {
7011 hdd_err("Invalid device mode %d", adapter->device_mode);
7012 return -EINVAL;
7013 }
7014
7015 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
7016 data, data_len, NULL)) {
7017 hdd_err("Invalid ATTR");
7018 return -EINVAL;
7019 }
7020
7021 memset(&params, 0, sizeof(params));
7022
7023 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
7024 params.ctl_flags = 1; /* set to default value */
7025 else
7026 params.ctl_flags = nla_get_u32(tb
7027 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
7028
7029 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
7030 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
7031 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
7032 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
7033 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
7034 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
7035 hdd_err("Attribute parsing failed");
7036 return -EINVAL;
7037 }
7038
7039 params.vdev_id = adapter->sessionId;
7040 params.freq = nla_get_u32(tb
7041 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
7042 if ((params.freq != 2412) && (params.freq != 2437) &&
7043 (params.freq != 2462)) {
7044 hdd_err("Invalid listening channel: %d", params.freq);
7045 return -EINVAL;
7046 }
7047
7048 params.period = nla_get_u32(tb
7049 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
7050 if (!((params.period > 0) && (params.period < UINT_MAX))) {
7051 hdd_err("Invalid period: %d", params.period);
7052 return -EINVAL;
7053 }
7054
7055 params.interval = nla_get_u32(tb
7056 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
7057 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
7058 hdd_err("Invalid interval: %d", params.interval);
7059 return -EINVAL;
7060 }
7061
7062 params.count = nla_get_u32(tb
7063 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08007064 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07007065 hdd_err("Invalid count: %d", params.count);
7066 return -EINVAL;
7067 }
7068
7069 params.device_types = nla_data(tb
7070 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
7071 if (params.device_types == NULL) {
7072 hdd_err("Invalid device types");
7073 return -EINVAL;
7074 }
7075
7076 params.dev_types_len = nla_len(tb
7077 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
7078 if (params.dev_types_len < 8) {
7079 hdd_err("Invalid device type length: %d", params.dev_types_len);
7080 return -EINVAL;
7081 }
7082
7083 params.probe_resp_tmplt = nla_data(tb
7084 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
7085 if (params.probe_resp_tmplt == NULL) {
7086 hdd_err("Invalid probe response template");
7087 return -EINVAL;
7088 }
7089
7090 params.probe_resp_len = nla_len(tb
7091 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
7092 if (params.probe_resp_len == 0) {
7093 hdd_err("Invalid probe resp template length: %d",
7094 params.probe_resp_len);
7095 return -EINVAL;
7096 }
7097
7098 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
7099 params.freq, params.period, params.interval, params.count);
7100
Wu Gao9a704f42017-03-10 18:42:11 +08007101 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07007102}
7103
7104
7105/**
7106 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
7107 * @wiphy: Pointer to wireless phy
7108 * @wdev: Pointer to wireless device
7109 * @data: Pointer to data
7110 * @data_len: Data length
7111 *
7112 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
7113 * to process p2p listen offload start vendor command.
7114 *
7115 * Return: 0 on success, negative errno on failure
7116 */
7117static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
7118 struct wireless_dev *wdev,
7119 const void *data,
7120 int data_len)
7121{
7122 int ret = 0;
7123
7124 cds_ssr_protect(__func__);
7125 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
7126 data, data_len);
7127 cds_ssr_unprotect(__func__);
7128
7129 return ret;
7130}
7131
7132/**
7133 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7134 * @wiphy: Pointer to wireless phy
7135 * @wdev: Pointer to wireless device
7136 * @data: Pointer to data
7137 * @data_len: Data length
7138 *
7139 * This function is to process the p2p listen offload stop vendor
7140 * command. It invokes WMA API to send command to firmware.
7141 *
7142 * Return: 0 on success, negative errno on failure
7143 */
7144static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7145 struct wireless_dev *wdev,
7146 const void *data,
7147 int data_len)
7148{
Peng Xu8fdaa492016-06-22 10:20:47 -07007149 hdd_adapter_t *adapter;
7150 struct net_device *dev = wdev->netdev;
7151
7152 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7153 hdd_err("Command not allowed in FTM mode");
7154 return -EPERM;
7155 }
7156
7157 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7158 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
7159 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
7160 (adapter->device_mode != QDF_P2P_GO_MODE)) {
7161 hdd_err("Invalid device mode");
7162 return -EINVAL;
7163 }
7164
Wu Gao9a704f42017-03-10 18:42:11 +08007165 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07007166}
7167
7168/**
7169 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7170 * @wiphy: Pointer to wireless phy
7171 * @wdev: Pointer to wireless device
7172 * @data: Pointer to data
7173 * @data_len: Data length
7174 *
7175 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
7176 * to process p2p listen offload stop vendor command.
7177 *
7178 * Return: 0 on success, negative errno on failure
7179 */
7180static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7181 struct wireless_dev *wdev,
7182 const void *data,
7183 int data_len)
7184{
7185 int ret = 0;
7186
7187 cds_ssr_protect(__func__);
7188 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
7189 data, data_len);
7190 cds_ssr_unprotect(__func__);
7191
7192 return ret;
7193}
7194
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307195/**
7196 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
7197 * @wiphy: Pointer to wireless phy
7198 * @wdev: Pointer to wireless device
7199 * @data: Pointer to data
7200 * @data_len: Data length
7201 *
7202 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
7203 * to process the conditional channel switch request.
7204 *
7205 * Return: 0 on success, negative errno on failure
7206 */
7207static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
7208 struct wireless_dev *wdev,
7209 const void *data,
7210 int data_len)
7211{
7212 int ret;
7213
7214 cds_ssr_protect(__func__);
7215 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
7216 data, data_len);
7217 cds_ssr_unprotect(__func__);
7218
7219 return ret;
7220}
7221
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307222/*
7223 * define short names for the global vendor params
7224 * used by __wlan_hdd_cfg80211_bpf_offload()
7225 */
7226#define BPF_INVALID \
7227 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
7228#define BPF_SET_RESET \
7229 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
7230#define BPF_VERSION \
7231 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
7232#define BPF_FILTER_ID \
7233 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
7234#define BPF_PACKET_SIZE \
7235 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
7236#define BPF_CURRENT_OFFSET \
7237 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
7238#define BPF_PROGRAM \
7239 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
7240#define BPF_MAX \
7241 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07007242
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307243static const struct nla_policy
7244wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
7245 [BPF_SET_RESET] = {.type = NLA_U32},
7246 [BPF_VERSION] = {.type = NLA_U32},
7247 [BPF_FILTER_ID] = {.type = NLA_U32},
7248 [BPF_PACKET_SIZE] = {.type = NLA_U32},
7249 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
7250 [BPF_PROGRAM] = {.type = NLA_U8},
7251};
7252
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007253struct bpf_offload_priv {
7254 struct sir_bpf_get_offload bpf_get_offload;
7255};
7256
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307257/**
7258 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007259 * @context: opaque context originally passed to SME. HDD always passes
7260 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307261 * @bpf_get_offload: struct for get offload
7262 *
7263 * This function receives the response/data from the lower layer and
7264 * checks to see if the thread is still waiting then post the results to
7265 * upper layer, if the request has timed out then ignore.
7266 *
7267 * Return: None
7268 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007269static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007270 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307271{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007272 struct hdd_request *request;
7273 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307274
7275 ENTER();
7276
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007277 request = hdd_request_get(context);
7278 if (!request) {
7279 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307280 return;
7281 }
7282
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007283 priv = hdd_request_priv(request);
7284 priv->bpf_get_offload = *data;
7285 hdd_request_complete(request);
7286 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307287}
7288
7289/**
7290 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
7291 * @hdd_context: hdd_context
7292 * @bpf_get_offload: struct for get offload
7293 *
7294 * Return: 0 on success, error number otherwise.
7295 */
7296static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
7297 struct sir_bpf_get_offload *bpf_get_offload)
7298{
7299 struct sk_buff *skb;
7300 uint32_t nl_buf_len;
7301
7302 ENTER();
7303
7304 nl_buf_len = NLMSG_HDRLEN;
7305 nl_buf_len +=
7306 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
7307 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
7308
7309 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7310 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007311 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307312 return -ENOMEM;
7313 }
7314
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007315 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307316 bpf_get_offload->bpf_version,
7317 bpf_get_offload->max_bytes_for_bpf_inst);
7318
7319 if (nla_put_u32(skb, BPF_PACKET_SIZE,
7320 bpf_get_offload->max_bytes_for_bpf_inst) ||
7321 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007322 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307323 goto nla_put_failure;
7324 }
7325
7326 cfg80211_vendor_cmd_reply(skb);
7327 EXIT();
7328 return 0;
7329
7330nla_put_failure:
7331 kfree_skb(skb);
7332 return -EINVAL;
7333}
7334
7335/**
7336 * hdd_get_bpf_offload - Get BPF offload Capabilities
7337 * @hdd_ctx: Hdd context
7338 *
7339 * Return: 0 on success, errno on failure
7340 */
7341static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
7342{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307343 QDF_STATUS status;
7344 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007345 void *cookie;
7346 struct hdd_request *request;
7347 struct bpf_offload_priv *priv;
7348 static const struct hdd_request_params params = {
7349 .priv_size = sizeof(*priv),
7350 .timeout_ms = WLAN_WAIT_TIME_BPF,
7351 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307352
7353 ENTER();
7354
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007355 request = hdd_request_alloc(&params);
7356 if (!request) {
7357 hdd_err("Unable to allocate request");
7358 return -EINVAL;
7359 }
7360 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307361
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007362 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7363 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007364 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307365 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007366 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007367 ret = qdf_status_to_os_return(status);
7368 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307369 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007370 ret = hdd_request_wait_for_response(request);
7371 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007372 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007373 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307374 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007375 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307376 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007377 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307378 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007379 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307380
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007381cleanup:
7382 /*
7383 * either we never sent a request to SME, we sent a request to
7384 * SME and timed out, or we sent a request to SME, received a
7385 * response from SME, and posted the response to userspace.
7386 * regardless we are done with the request.
7387 */
7388 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307389 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007390
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307391 return ret;
7392}
7393
7394/**
7395 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7396 * @hdd_ctx: Hdd context
7397 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307398 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307399 *
7400 * Return: 0 on success; errno on failure
7401 */
7402static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7403 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307404 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307405{
7406 struct sir_bpf_set_offload *bpf_set_offload;
7407 QDF_STATUS status;
7408 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307409 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307410
7411 ENTER();
7412
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307413 if (adapter->device_mode == QDF_STA_MODE ||
7414 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7415 if (!hdd_conn_is_connected(
7416 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7417 hdd_err("Not in Connected state!");
7418 return -ENOTSUPP;
7419 }
7420 }
7421
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307422 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7423 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007424 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307425 return -ENOMEM;
7426 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307427
7428 /* Parse and fetch bpf packet size */
7429 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007430 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307431 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307432 goto fail;
7433 }
7434 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7435
7436 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007437 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307438 goto post_sme;
7439 }
7440
7441 /* Parse and fetch bpf program */
7442 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007443 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307444 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307445 goto fail;
7446 }
7447
7448 prog_len = nla_len(tb[BPF_PROGRAM]);
7449 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307450
7451 if (bpf_set_offload->program == NULL) {
7452 hdd_err("qdf_mem_malloc failed for bpf offload program");
7453 ret = -ENOMEM;
7454 goto fail;
7455 }
7456
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307457 bpf_set_offload->current_length = prog_len;
7458 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307459 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307460
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007461 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007462 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307463 bpf_set_offload->program, prog_len);
7464
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307465 /* Parse and fetch filter Id */
7466 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007467 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307468 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307469 goto fail;
7470 }
7471 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7472
7473 /* Parse and fetch current offset */
7474 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007475 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307476 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307477 goto fail;
7478 }
7479 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7480
7481post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007482 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 +05307483 bpf_set_offload->session_id,
7484 bpf_set_offload->version,
7485 bpf_set_offload->filter_id,
7486 bpf_set_offload->total_length,
7487 bpf_set_offload->current_length,
7488 bpf_set_offload->current_offset);
7489
7490 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7491 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007492 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307493 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307494 goto fail;
7495 }
7496 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307497
7498fail:
7499 if (bpf_set_offload->current_length)
7500 qdf_mem_free(bpf_set_offload->program);
7501 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307502 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307503}
7504
7505/**
7506 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7507 * @wiphy: wiphy structure pointer
7508 * @wdev: Wireless device structure pointer
7509 * @data: Pointer to the data received
7510 * @data_len: Length of @data
7511 *
7512 * Return: 0 on success; errno on failure
7513 */
7514static int
7515__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7516 struct wireless_dev *wdev,
7517 const void *data, int data_len)
7518{
7519 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7520 struct net_device *dev = wdev->netdev;
7521 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7522 struct nlattr *tb[BPF_MAX + 1];
7523 int ret_val, packet_filter_subcmd;
7524
7525 ENTER();
7526
7527 ret_val = wlan_hdd_validate_context(hdd_ctx);
7528 if (ret_val)
7529 return ret_val;
7530
7531 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007532 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307533 return -EINVAL;
7534 }
7535
7536 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007537 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307538 return -ENOTSUPP;
7539 }
7540
7541 if (nla_parse(tb, BPF_MAX, data, data_len,
7542 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007543 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307544 return -EINVAL;
7545 }
7546
7547 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007548 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307549 return -EINVAL;
7550 }
7551
7552 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7553
7554 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7555 return hdd_get_bpf_offload(hdd_ctx);
7556 else
7557 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307558 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307559}
7560
7561/**
7562 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7563 * @wiphy: wiphy structure pointer
7564 * @wdev: Wireless device structure pointer
7565 * @data: Pointer to the data received
7566 * @data_len: Length of @data
7567 *
7568 * Return: 0 on success; errno on failure
7569 */
7570
7571static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7572 struct wireless_dev *wdev,
7573 const void *data, int data_len)
7574{
7575 int ret;
7576
7577 cds_ssr_protect(__func__);
7578 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7579 cds_ssr_unprotect(__func__);
7580
7581 return ret;
7582}
7583
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307584/**
7585 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7586 * @pre_cac_adapter: AP adapter used for pre cac
7587 * @status: Status (true or false)
7588 * @handle: Global handle
7589 *
7590 * Sets the status of pre cac i.e., whether the pre cac is active or not
7591 *
7592 * Return: Zero on success, non-zero on failure
7593 */
7594static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7595 bool status, tHalHandle handle)
7596{
7597 QDF_STATUS ret;
7598
7599 ret = wlan_sap_set_pre_cac_status(
7600 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7601 if (QDF_IS_STATUS_ERROR(ret))
7602 return -EINVAL;
7603
7604 return 0;
7605}
7606
7607/**
7608 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7609 * @ap_adapter: AP adapter
7610 * @chan_before_pre_cac: Channel
7611 *
7612 * Saves the channel which the AP was beaconing on before moving to the pre
7613 * cac channel. If radar is detected on the pre cac channel, this saved
7614 * channel will be used for AP operations.
7615 *
7616 * Return: Zero on success, non-zero on failure
7617 */
7618static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7619 uint8_t chan_before_pre_cac)
7620{
7621 QDF_STATUS ret;
7622
7623 ret = wlan_sap_set_chan_before_pre_cac(
7624 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7625 if (QDF_IS_STATUS_ERROR(ret))
7626 return -EINVAL;
7627
7628 return 0;
7629}
7630
7631/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307632 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7633 * are in nol list from provided channel list
7634 * @adapter: AP adapter
7635 * @channel_count: channel count
7636 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307637 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307638 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307639 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307640static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7641 uint32_t *channel_count,
7642 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307643{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307644 uint8_t i, j;
7645 uint32_t nol_len = 0;
7646 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7647 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7648 uint32_t chan_count;
7649 bool found;
7650 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307651
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307652 if (!hdd_ctx) {
7653 hdd_err("hdd ctx not found");
7654 *channel_count = 0;
7655 return;
7656 }
7657
7658 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7659 hdd_err("invalid channel count %d", *channel_count);
7660 return;
7661 }
7662
7663 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7664 if (nol_len == 0)
7665 return;
7666
7667 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7668 chan_count = *channel_count;
7669 qdf_mem_zero(channel_list, chan_count);
7670 *channel_count = 0;
7671
7672 for (i = 0 ; i < chan_count; i++) {
7673 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7674 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7675 continue;
7676 found = false;
7677 for (j = 0; j < nol_len; j++) {
7678 if (tmp_chan_list[i] == nol[j]) {
7679 found = true;
7680 hdd_notice("skipped channel %d due to nol",
7681 nol[j]);
7682 break;
7683 }
7684 }
7685 if (!found) {
7686 channel_list[*channel_count] = tmp_chan_list[i];
7687 *channel_count = *channel_count + 1;
7688 }
7689 }
7690}
7691
7692int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7693 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307694 uint8_t *channel_list,
7695 eCsrBand band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307696{
7697 tsap_Config_t *sap_config;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307698 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7699 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7700 uint32_t chan_count;
7701 uint8_t i;
7702 QDF_STATUS status;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307703
7704 sap_config = &adapter->sessionCtx.ap.sapConfig;
7705
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307706 status =
7707 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7708 tmp_chan_list,
7709 &chan_count);
7710 if (QDF_IS_STATUS_ERROR(status)) {
7711 hdd_err("Failed to get channel list");
7712 return -EINVAL;
7713 }
7714 for (i = 0; i < chan_count; i++) {
7715 if (*channel_count < QDF_MAX_NUM_CHAN) {
7716 if ((eCSR_BAND_24 == band) &&
7717 (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
7718 channel_list[*channel_count] = tmp_chan_list[i];
7719 *channel_count += 1;
7720 } else if ((eCSR_BAND_5G == band) &&
7721 (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
7722 channel_list[*channel_count] = tmp_chan_list[i];
7723 *channel_count += 1;
7724 }
7725 } else {
7726 break;
7727 }
7728 }
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307729 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307730 if (*channel_count == 0) {
7731 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307732 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307733 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307734
7735 return 0;
7736}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307737
7738/**
7739 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7740 * @hdd_ctx: HDD context
7741 * @ap_adapter: AP adapter
7742 * @channel: Channel requested by userspace
7743 * @pre_cac_chan: Pointer to the pre CAC channel
7744 *
7745 * Validates the channel provided by userspace. If user provided channel 0,
7746 * a valid outdoor channel must be selected from the regulatory channel.
7747 *
7748 * Return: Zero on success and non zero value on error
7749 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007750static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7751 hdd_adapter_t *ap_adapter,
7752 uint8_t channel,
7753 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307754{
7755 uint32_t i, j;
7756 QDF_STATUS status;
7757 int ret;
7758 uint8_t nol[QDF_MAX_NUM_CHAN];
7759 uint32_t nol_len = 0, weight_len = 0;
7760 bool found;
7761 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7762 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7763 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7764
7765 if (0 == channel) {
7766 /* Channel is not obtained from PCL because PCL may not have
7767 * the entire channel list. For example: if SAP is up on
7768 * channel 6 and PCL is queried for the next SAP interface,
7769 * if SCC is preferred, the PCL will contain only the channel
7770 * 6. But, we are in need of a DFS channel. So, going with the
7771 * first channel from the valid channel list.
7772 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007773 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7774 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307775 if (QDF_IS_STATUS_ERROR(status)) {
7776 hdd_err("Failed to get channel list");
7777 return -EINVAL;
7778 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007779 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307780 pcl_weights, weight_len);
7781 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7782 for (i = 0; i < len; i++) {
7783 found = false;
7784 for (j = 0; j < nol_len; j++) {
7785 if (channel_list[i] == nol[j]) {
7786 found = true;
7787 break;
7788 }
7789 }
7790 if (found)
7791 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007792 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7793 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307794 *pre_cac_chan = channel_list[i];
7795 break;
7796 }
7797 }
7798 if (*pre_cac_chan == 0) {
7799 hdd_err("unable to find outdoor channel");
7800 return -EINVAL;
7801 }
7802 } else {
7803 /* Only when driver selects a channel, check is done for
7804 * unnsafe and NOL channels. When user provides a fixed channel
7805 * the user is expected to take care of this.
7806 */
7807 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007808 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307809 hdd_err("Invalid channel for pre cac:%d", channel);
7810 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307811 }
Jeff Johnson68755312017-02-10 11:46:55 -08007812
7813 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307814 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007815 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307816 return 0;
7817}
7818
7819/**
7820 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7821 * @channel: Channel option provided by userspace
7822 *
7823 * Sets the driver to the required hardware mode and start an adapater for
7824 * pre CAC which will mimic an AP.
7825 *
7826 * Return: Zero on success, non-zero value on error
7827 */
7828int wlan_hdd_request_pre_cac(uint8_t channel)
7829{
Krunal Sonib37bb352016-12-20 14:12:21 -08007830 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307831 hdd_context_t *hdd_ctx;
7832 int ret;
7833 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7834 hdd_ap_ctx_t *hdd_ap_ctx;
7835 QDF_STATUS status;
7836 struct wiphy *wiphy;
7837 struct net_device *dev;
7838 struct cfg80211_chan_def chandef;
7839 enum nl80211_channel_type channel_type;
7840 uint32_t freq;
7841 struct ieee80211_channel *chan;
7842 tHalHandle handle;
7843 bool val;
7844
7845 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7846 if (0 != wlan_hdd_validate_context(hdd_ctx))
7847 return -EINVAL;
7848
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007849 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307850 hdd_err("pre cac not allowed in concurrency");
7851 return -EINVAL;
7852 }
7853
7854 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7855 if (!ap_adapter) {
7856 hdd_err("unable to get SAP adapter");
7857 return -EINVAL;
7858 }
7859
7860 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7861 if (!handle) {
7862 hdd_err("Invalid handle");
7863 return -EINVAL;
7864 }
7865
7866 val = wlan_sap_is_pre_cac_active(handle);
7867 if (val) {
7868 hdd_err("pre cac is already in progress");
7869 return -EINVAL;
7870 }
7871
7872 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7873 if (!hdd_ap_ctx) {
7874 hdd_err("SAP context is NULL");
7875 return -EINVAL;
7876 }
7877
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007878 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7879 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307880 hdd_err("SAP is already on DFS channel:%d",
7881 hdd_ap_ctx->operatingChannel);
7882 return -EINVAL;
7883 }
7884
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007885 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307886 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7887 hdd_ap_ctx->operatingChannel);
7888 return -EINVAL;
7889 }
7890
Krunal Sonib37bb352016-12-20 14:12:21 -08007891 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7892 if (!mac_addr) {
7893 hdd_err("can't add virtual intf: Not getting valid mac addr");
7894 return -EINVAL;
7895 }
7896
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007897 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307898
7899 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7900 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007901 if (ret != 0) {
7902 hdd_err("can't validate pre-cac channel");
7903 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307904 }
7905
7906 hdd_debug("starting pre cac SAP adapter");
7907
7908 /* Starting a SAP adapter:
7909 * Instead of opening an adapter, we could just do a SME open session
7910 * for AP type. But, start BSS would still need an adapter.
7911 * So, this option is not taken.
7912 *
7913 * hdd open adapter is going to register this precac interface with
7914 * user space. This interface though exposed to user space will be in
7915 * DOWN state. Consideration was done to avoid this registration to the
7916 * user space. But, as part of SAP operations multiple events are sent
7917 * to user space. Some of these events received from unregistered
7918 * interface was causing crashes. So, retaining the registration.
7919 *
7920 * So, this interface would remain registered and will remain in DOWN
7921 * state for the CAC duration. We will add notes in the feature
7922 * announcement to not use this temporary interface for any activity
7923 * from user space.
7924 */
7925 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007926 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307927 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307928 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007929 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307930 }
7931
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307932 /*
7933 * This interface is internally created by the driver. So, no interface
7934 * up comes for this interface from user space and hence starting
7935 * the adapter internally.
7936 */
7937 if (hdd_start_adapter(pre_cac_adapter)) {
7938 hdd_err("error starting the pre cac adapter");
7939 goto close_pre_cac_adapter;
7940 }
7941
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307942 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7943
7944 wiphy = hdd_ctx->wiphy;
7945 dev = pre_cac_adapter->dev;
7946
7947 /* Since this is only a dummy interface lets us use the IEs from the
7948 * other active SAP interface. In regular scenarios, these IEs would
7949 * come from the user space entity
7950 */
7951 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7952 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7953 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7954 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307955 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307956 }
7957 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7958 ap_adapter->sessionCtx.ap.beacon,
7959 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7960 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7961 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7962 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7963 ap_adapter->sessionCtx.ap.sapConfig.authType;
7964
7965 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7966 * to operate on the same bandwidth as that of the 2.4GHz operations.
7967 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7968 */
7969 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7970 case CH_WIDTH_20MHZ:
7971 channel_type = NL80211_CHAN_HT20;
7972 break;
7973 case CH_WIDTH_40MHZ:
7974 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7975 ap_adapter->sessionCtx.ap.sapConfig.channel)
7976 channel_type = NL80211_CHAN_HT40PLUS;
7977 else
7978 channel_type = NL80211_CHAN_HT40MINUS;
7979 break;
7980 default:
7981 channel_type = NL80211_CHAN_NO_HT;
7982 break;
7983 }
7984
7985 freq = cds_chan_to_freq(pre_cac_chan);
7986 chan = __ieee80211_get_channel(wiphy, freq);
7987 if (!chan) {
7988 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307989 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307990 }
7991
7992 cfg80211_chandef_create(&chandef, chan, channel_type);
7993
7994 hdd_debug("orig width:%d channel_type:%d freq:%d",
7995 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7996 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007997 /*
7998 * Doing update after opening and starting pre-cac adapter will make
7999 * sure that driver won't do hardware mode change if there are any
8000 * initial hick-ups or issues in pre-cac adapter's configuration.
8001 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
8002 * connection update should result in DBS mode
8003 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008004 status = policy_mgr_update_and_wait_for_connection_update(
8005 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08008006 ap_adapter->sessionId,
8007 pre_cac_chan,
8008 SIR_UPDATE_REASON_PRE_CAC);
8009 if (QDF_IS_STATUS_ERROR(status)) {
8010 hdd_err("error in moving to DBS mode");
8011 goto stop_close_pre_cac_adapter;
8012 }
8013
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308014
8015 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
8016 if (0 != ret) {
8017 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308018 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308019 }
8020
8021 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
8022 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08008023 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308024 if (QDF_IS_STATUS_ERROR(status)) {
8025 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308026 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308027 }
8028
8029 /*
8030 * The pre cac status is set here. But, it would not be reset explicitly
8031 * anywhere, since after the pre cac success/failure, the pre cac
8032 * adapter itself would be removed.
8033 */
8034 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
8035 if (0 != ret) {
8036 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308037 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308038 }
8039
8040 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
8041 hdd_ap_ctx->operatingChannel);
8042 if (0 != ret) {
8043 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308044 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308045 }
8046
8047 ap_adapter->pre_cac_chan = pre_cac_chan;
8048
8049 return 0;
8050
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308051stop_close_pre_cac_adapter:
8052 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308053 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
8054 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308055close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308056 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08008057release_intf_addr_and_return_failure:
8058 /*
8059 * Release the interface address as the adapter
8060 * failed to start, if you don't release then next
8061 * adapter which is trying to come wouldn't get valid
8062 * mac address. Remember we have limited pool of mac addresses
8063 */
8064 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308065 return -EINVAL;
8066}
8067
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308068static const struct nla_policy
8069wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
8070 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
8071};
8072
Agrawal Ashish65634612016-08-18 13:24:32 +05308073static const struct nla_policy
8074wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
8075 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
8076 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
8077};
8078
8079/**
8080 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
8081 * @wiphy: Pointer to wireless phy
8082 * @wdev: Pointer to wireless device
8083 * @data: Pointer to data
8084 * @data_len: Length of @data
8085 *
8086 * This function parses the incoming NL vendor command data attributes and
8087 * updates the SAP context about channel_hint and DFS mode.
8088 * If channel_hint is set, SAP will choose that channel
8089 * as operating channel.
8090 *
8091 * If DFS mode is enabled, driver will include DFS channels
8092 * in ACS else driver will skip DFS channels.
8093 *
8094 * Return: 0 on success, negative errno on failure
8095 */
8096static int
8097__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8098 struct wireless_dev *wdev,
8099 const void *data, int data_len)
8100{
8101 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8102 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
8103 int ret;
8104 struct acs_dfs_policy *acs_policy;
8105 int mode = DFS_MODE_NONE;
8106 int channel_hint = 0;
8107
8108 ENTER_DEV(wdev->netdev);
8109
8110 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8111 hdd_err("Command not allowed in FTM mode");
8112 return -EINVAL;
8113 }
8114
8115 ret = wlan_hdd_validate_context(hdd_ctx);
8116 if (0 != ret)
8117 return ret;
8118
8119 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
8120 data, data_len,
8121 wlan_hdd_set_acs_dfs_config_policy)) {
8122 hdd_err("invalid attr");
8123 return -EINVAL;
8124 }
8125
8126 acs_policy = &hdd_ctx->acs_policy;
8127 /*
8128 * SCM sends this attribute to restrict SAP from choosing
8129 * DFS channels from ACS.
8130 */
8131 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
8132 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
8133
8134 if (!IS_DFS_MODE_VALID(mode)) {
8135 hdd_err("attr acs dfs mode is not valid");
8136 return -EINVAL;
8137 }
8138 acs_policy->acs_dfs_mode = mode;
8139
8140 /*
8141 * SCM sends this attribute to provide an active channel,
8142 * to skip redundant ACS between drivers, and save driver start up time
8143 */
8144 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
8145 channel_hint = nla_get_u8(
8146 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
8147
8148 if (!IS_CHANNEL_VALID(channel_hint)) {
8149 hdd_err("acs channel is not valid");
8150 return -EINVAL;
8151 }
8152 acs_policy->acs_channel = channel_hint;
8153
8154 return 0;
8155}
8156
8157/**
8158 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
8159 * @wiphy: wiphy structure pointer
8160 * @wdev: Wireless device structure pointer
8161 * @data: Pointer to the data received
8162 * @data_len: Length of @data
8163 *
8164 * This function parses the incoming NL vendor command data attributes and
8165 * updates the SAP context about channel_hint and DFS mode.
8166 *
8167 * Return: 0 on success; errno on failure
8168 */
8169static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8170 struct wireless_dev *wdev,
8171 const void *data, int data_len)
8172{
8173 int ret;
8174
8175 cds_ssr_protect(__func__);
8176 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
8177 cds_ssr_unprotect(__func__);
8178
8179 return ret;
8180}
8181
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308182/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308183 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
8184 * @mode : cfg80211 dfs mode
8185 *
8186 * Return: return csr sta roam dfs mode else return NONE
8187 */
8188static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
8189 enum dfs_mode mode)
8190{
8191 switch (mode) {
8192 case DFS_MODE_ENABLE:
8193 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
8194 break;
8195 case DFS_MODE_DISABLE:
8196 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
8197 break;
8198 case DFS_MODE_DEPRIORITIZE:
8199 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
8200 break;
8201 default:
8202 hdd_err("STA Roam policy dfs mode is NONE");
8203 return CSR_STA_ROAM_POLICY_NONE;
8204 }
8205}
8206
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308207/*
8208 * hdd_get_sap_operating_band: Get current operating channel
8209 * for sap.
8210 * @hdd_ctx: hdd context
8211 *
8212 * Return : Corresponding band for SAP operating channel
8213 */
8214uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
8215{
8216 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8217 QDF_STATUS status;
8218 hdd_adapter_t *adapter;
8219 uint8_t operating_channel = 0;
8220 uint8_t sap_operating_band = 0;
8221 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8222 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8223 adapter = adapter_node->pAdapter;
8224
8225 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
8226 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8227 &next);
8228 adapter_node = next;
8229 continue;
8230 }
8231 operating_channel = adapter->sessionCtx.ap.operatingChannel;
8232 if (IS_24G_CH(operating_channel))
8233 sap_operating_band = eCSR_BAND_24;
8234 else if (IS_5G_CH(operating_channel))
8235 sap_operating_band = eCSR_BAND_5G;
8236 else
8237 sap_operating_band = eCSR_BAND_ALL;
8238 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8239 &next);
bings373b99b2017-01-23 10:35:08 +08008240 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308241 }
8242 return sap_operating_band;
8243}
8244
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308245static const struct nla_policy
8246wlan_hdd_set_sta_roam_config_policy[
8247QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
8248 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
8249 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
8250};
8251
8252/**
8253 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
8254 * for station connection or roaming.
8255 * @wiphy: Pointer to wireless phy
8256 * @wdev: Pointer to wireless device
8257 * @data: Pointer to data
8258 * @data_len: Length of @data
8259 *
8260 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8261 * channels needs to be skipped in scanning or not.
8262 * If dfs_mode is disabled, driver will not scan DFS channels.
8263 * If skip_unsafe_channels is set, driver will skip unsafe channels
8264 * in Scanning.
8265 *
8266 * Return: 0 on success, negative errno on failure
8267 */
8268static int
8269__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8270 struct wireless_dev *wdev,
8271 const void *data, int data_len)
8272{
8273 struct net_device *dev = wdev->netdev;
8274 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8275 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8276 struct nlattr *tb[
8277 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8278 int ret;
8279 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8280 enum dfs_mode mode = DFS_MODE_NONE;
8281 bool skip_unsafe_channels = false;
8282 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308283 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308284
8285 ENTER_DEV(dev);
8286
8287 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8288 hdd_err("Command not allowed in FTM mode");
8289 return -EINVAL;
8290 }
8291
8292 ret = wlan_hdd_validate_context(hdd_ctx);
8293 if (0 != ret)
8294 return ret;
8295 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8296 data, data_len,
8297 wlan_hdd_set_sta_roam_config_policy)) {
8298 hdd_err("invalid attr");
8299 return -EINVAL;
8300 }
8301 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8302 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8303 if (!IS_DFS_MODE_VALID(mode)) {
8304 hdd_err("attr sta roam dfs mode policy is not valid");
8305 return -EINVAL;
8306 }
8307
8308 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8309
8310 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8311 skip_unsafe_channels = nla_get_u8(
8312 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308313 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308314 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308315 skip_unsafe_channels, adapter->sessionId,
8316 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308317
8318 if (!QDF_IS_STATUS_SUCCESS(status)) {
8319 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8320 return -EINVAL;
8321 }
8322 return 0;
8323}
8324
8325/**
8326 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8327 * connection and roaming for station.
8328 * @wiphy: wiphy structure pointer
8329 * @wdev: Wireless device structure pointer
8330 * @data: Pointer to the data received
8331 * @data_len: Length of @data
8332 *
8333 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8334 * channels needs to be skipped in scanning or not.
8335 * If dfs_mode is disabled, driver will not scan DFS channels.
8336 * If skip_unsafe_channels is set, driver will skip unsafe channels
8337 * in Scanning.
8338 * Return: 0 on success; errno on failure
8339 */
8340static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8341 struct wireless_dev *wdev,
8342 const void *data, int data_len)
8343{
8344 int ret;
8345
8346 cds_ssr_protect(__func__);
8347 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
8348 cds_ssr_unprotect(__func__);
8349
8350 return ret;
8351}
8352
Agrawal Ashish467dde42016-09-08 18:44:22 +05308353#ifdef FEATURE_WLAN_CH_AVOID
8354/**
8355 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8356 * is on unsafe channel.
8357 * @wiphy: wiphy structure pointer
8358 * @wdev: Wireless device structure pointer
8359 * @data: Pointer to the data received
8360 * @data_len: Length of @data
8361 *
8362 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8363 * on any of unsafe channels.
8364 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8365 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8366 *
8367 * Return: 0 on success; errno on failure
8368 */
8369static int
8370__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8371 struct wireless_dev *wdev,
8372 const void *data, int data_len)
8373{
8374 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8375 int ret;
8376 uint16_t unsafe_channel_count;
8377 int unsafe_channel_index;
8378 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8379
8380 ENTER_DEV(wdev->netdev);
8381
8382 if (!qdf_ctx) {
8383 cds_err("qdf_ctx is NULL");
8384 return -EINVAL;
8385 }
8386
8387 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8388 hdd_err("Command not allowed in FTM mode");
8389 return -EINVAL;
8390 }
8391
8392 ret = wlan_hdd_validate_context(hdd_ctx);
8393 if (0 != ret)
8394 return ret;
8395 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8396 &(hdd_ctx->unsafe_channel_count),
8397 sizeof(hdd_ctx->unsafe_channel_list));
8398
8399 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8400 (uint16_t)NUM_CHANNELS);
8401 for (unsafe_channel_index = 0;
8402 unsafe_channel_index < unsafe_channel_count;
8403 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008404 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308405 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8406 }
8407 hdd_unsafe_channel_restart_sap(hdd_ctx);
8408 return 0;
8409}
8410
8411/**
8412 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8413 * is on unsafe channel.
8414 * @wiphy: wiphy structure pointer
8415 * @wdev: Wireless device structure pointer
8416 * @data: Pointer to the data received
8417 * @data_len: Length of @data
8418 *
8419 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8420 * on any of unsafe channels.
8421 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8422 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8423 *
8424 * Return: 0 on success; errno on failure
8425 */
8426static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8427 struct wireless_dev *wdev,
8428 const void *data, int data_len)
8429{
8430 int ret;
8431
8432 cds_ssr_protect(__func__);
8433 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8434 cds_ssr_unprotect(__func__);
8435
8436 return ret;
8437}
8438
8439#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308440/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308441 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8442 * SAP is on unsafe channel.
8443 * @wiphy: wiphy structure pointer
8444 * @wdev: Wireless device structure pointer
8445 * @data: Pointer to the data received
8446 * @data_len: Length of @data
8447 *
8448 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8449 * driver.
8450 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8451 * will initiate restart of sap.
8452 *
8453 * Return: 0 on success; errno on failure
8454 */
8455static int
8456__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8457 struct wireless_dev *wdev,
8458 const void *data, int data_len)
8459{
8460 struct net_device *ndev = wdev->netdev;
8461 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8462 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8463 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8464 uint8_t config_channel = 0;
8465 hdd_ap_ctx_t *ap_ctx;
8466 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308467 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308468
8469 ENTER();
8470
8471 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008472 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308473 return -EINVAL;
8474 }
8475
8476 ret = wlan_hdd_validate_context(hdd_ctx);
8477 if (0 != ret)
8478 return -EINVAL;
8479
8480 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8481 data, data_len,
8482 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008483 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308484 return -EINVAL;
8485 }
8486
8487 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8488 if (!test_bit(SOFTAP_BSS_STARTED,
8489 &hostapd_adapter->event_flags)) {
8490 hdd_err("SAP is not started yet. Restart sap will be invalid");
8491 return -EINVAL;
8492 }
8493
8494 config_channel =
8495 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8496
8497 if (!((IS_24G_CH(config_channel)) ||
8498 (IS_5G_CH(config_channel)))) {
8499 hdd_err("Channel %d is not valid to restart SAP",
8500 config_channel);
8501 return -ENOTSUPP;
8502 }
8503
8504 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8505 ap_ctx->sapConfig.channel = config_channel;
8506 ap_ctx->sapConfig.ch_params.ch_width =
8507 ap_ctx->sapConfig.ch_width_orig;
8508
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008509 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8510 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308511 ap_ctx->sapConfig.sec_ch,
8512 &ap_ctx->sapConfig.ch_params);
8513
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008514 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308515 }
8516
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308517 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8518 uint32_t freq_len, i;
8519 uint32_t *freq;
8520 uint8_t chans[QDF_MAX_NUM_CHAN];
8521
8522 hdd_debug("setting mandatory freq/chan list");
8523
8524 freq_len = nla_len(
8525 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8526 sizeof(uint32_t);
8527
8528 if (freq_len > QDF_MAX_NUM_CHAN) {
8529 hdd_err("insufficient space to hold channels");
8530 return -ENOMEM;
8531 }
8532
8533 freq = nla_data(
8534 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8535
8536 hdd_debug("freq_len=%d", freq_len);
8537
8538 for (i = 0; i < freq_len; i++) {
8539 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8540 hdd_debug("freq[%d]=%d", i, freq[i]);
8541 }
8542
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008543 status = policy_mgr_set_sap_mandatory_channels(
8544 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308545 if (QDF_IS_STATUS_ERROR(status))
8546 return -EINVAL;
8547 }
8548
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308549 return 0;
8550}
8551
8552/**
8553 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8554 * @wiphy: wiphy structure pointer
8555 * @wdev: Wireless device structure pointer
8556 * @data: Pointer to the data received
8557 * @data_len: Length of @data
8558 *
8559 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8560 * driver.
8561 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8562 * will initiate restart of sap.
8563 *
8564 * Return: 0 on success; errno on failure
8565 */
8566static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8567 struct wireless_dev *wdev,
8568 const void *data, int data_len)
8569{
8570 int ret;
8571
8572 cds_ssr_protect(__func__);
8573 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8574 wdev, data, data_len);
8575 cds_ssr_unprotect(__func__);
8576
8577 return ret;
8578}
8579
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308580#undef BPF_INVALID
8581#undef BPF_SET_RESET
8582#undef BPF_VERSION
8583#undef BPF_ID
8584#undef BPF_PACKET_SIZE
8585#undef BPF_CURRENT_OFFSET
8586#undef BPF_PROGRAM
8587#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308588
8589/**
8590 * define short names for the global vendor params
8591 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8592 */
8593#define PARAM_TOTAL_CMD_EVENT_WAKE \
8594 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8595#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8596 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8597#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8598 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8599#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8600 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8601#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8602 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8603#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8604 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8605#define PARAM_TOTAL_RX_DATA_WAKE \
8606 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8607#define PARAM_RX_UNICAST_CNT \
8608 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8609#define PARAM_RX_MULTICAST_CNT \
8610 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8611#define PARAM_RX_BROADCAST_CNT \
8612 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8613#define PARAM_ICMP_PKT \
8614 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8615#define PARAM_ICMP6_PKT \
8616 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8617#define PARAM_ICMP6_RA \
8618 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8619#define PARAM_ICMP6_NA \
8620 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8621#define PARAM_ICMP6_NS \
8622 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8623#define PARAM_ICMP4_RX_MULTICAST_CNT \
8624 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8625#define PARAM_ICMP6_RX_MULTICAST_CNT \
8626 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8627#define PARAM_OTHER_RX_MULTICAST_CNT \
8628 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308629#define PARAM_RSSI_BREACH_CNT \
8630 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8631#define PARAM_LOW_RSSI_CNT \
8632 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8633#define PARAM_GSCAN_CNT \
8634 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8635#define PARAM_PNO_COMPLETE_CNT \
8636 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8637#define PARAM_PNO_MATCH_CNT \
8638 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8639
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308640
8641
8642/**
8643 * hdd_send_wakelock_stats() - API to send wakelock stats
8644 * @ctx: context to be passed to callback
8645 * @data: data passed to callback
8646 *
8647 * This function is used to send wake lock stats to HAL layer
8648 *
8649 * Return: 0 on success, error number otherwise.
8650 */
8651static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8652 const struct sir_wake_lock_stats *data)
8653{
8654 struct sk_buff *skb;
8655 uint32_t nl_buf_len;
8656 uint32_t total_rx_data_wake, rx_multicast_cnt;
8657 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308658 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308659
8660 ENTER();
8661
8662 nl_buf_len = NLMSG_HDRLEN;
8663 nl_buf_len +=
8664 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8665 (NLMSG_HDRLEN + sizeof(uint32_t));
8666
8667 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8668
8669 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008670 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308671 return -ENOMEM;
8672 }
8673
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008674 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308675 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008676 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308677 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008678 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308679 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008680 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308681 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008682 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308683 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008684 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308685 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008686 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308687 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008688 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8689 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308690 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008691 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308692 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008693 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308694 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008695 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308696 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008697 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308698 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008699 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308700 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308701
8702 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308703 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308704
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308705 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308706 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308707
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308708 rx_multicast_cnt =
8709 data->wow_ipv4_mcast_wake_up_count +
8710 ipv6_rx_multicast_addr_cnt;
8711
8712 total_rx_data_wake =
8713 data->wow_ucast_wake_up_count +
8714 data->wow_bcast_wake_up_count +
8715 rx_multicast_cnt;
8716
8717 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8718 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8719 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8720 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8721 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8722 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8723 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8724 total_rx_data_wake) ||
8725 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8726 data->wow_ucast_wake_up_count) ||
8727 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8728 rx_multicast_cnt) ||
8729 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8730 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308731 nla_put_u32(skb, PARAM_ICMP_PKT,
8732 data->wow_icmpv4_count) ||
8733 nla_put_u32(skb, PARAM_ICMP6_PKT,
8734 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308735 nla_put_u32(skb, PARAM_ICMP6_RA,
8736 data->wow_ipv6_mcast_ra_stats) ||
8737 nla_put_u32(skb, PARAM_ICMP6_NA,
8738 data->wow_ipv6_mcast_na_stats) ||
8739 nla_put_u32(skb, PARAM_ICMP6_NS,
8740 data->wow_ipv6_mcast_ns_stats) ||
8741 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8742 data->wow_ipv4_mcast_wake_up_count) ||
8743 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8744 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308745 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8746 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8747 data->wow_rssi_breach_wake_up_count) ||
8748 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8749 data->wow_low_rssi_wake_up_count) ||
8750 nla_put_u32(skb, PARAM_GSCAN_CNT,
8751 data->wow_gscan_wake_up_count) ||
8752 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8753 data->wow_pno_complete_wake_up_count) ||
8754 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8755 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008756 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308757 goto nla_put_failure;
8758 }
8759
8760 cfg80211_vendor_cmd_reply(skb);
8761
8762 EXIT();
8763 return 0;
8764
8765nla_put_failure:
8766 kfree_skb(skb);
8767 return -EINVAL;
8768}
8769
8770/**
8771 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8772 * @wiphy: wiphy pointer
8773 * @wdev: pointer to struct wireless_dev
8774 * @data: pointer to incoming NL vendor data
8775 * @data_len: length of @data
8776 *
8777 * This function parses the incoming NL vendor command data attributes and
8778 * invokes the SME Api and blocks on a completion variable.
8779 * WMA copies required data and invokes callback
8780 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8781 *
8782 * Return: 0 on success; error number otherwise.
8783 */
8784static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8785 struct wireless_dev *wdev,
8786 const void *data,
8787 int data_len)
8788{
8789 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8790 int status, ret;
8791 struct sir_wake_lock_stats wake_lock_stats;
8792 QDF_STATUS qdf_status;
8793
8794 ENTER();
8795
8796 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008797 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308798 return -EINVAL;
8799 }
8800
8801 status = wlan_hdd_validate_context(hdd_ctx);
8802 if (0 != status)
8803 return -EINVAL;
8804
8805 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8806 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008807 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308808 return -EINVAL;
8809 }
8810
8811 ret = hdd_send_wakelock_stats(hdd_ctx,
8812 &wake_lock_stats);
8813 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008814 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308815
8816 EXIT();
8817 return ret;
8818}
8819
8820/**
8821 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8822 * @wiphy: wiphy pointer
8823 * @wdev: pointer to struct wireless_dev
8824 * @data: pointer to incoming NL vendor data
8825 * @data_len: length of @data
8826 *
8827 * This function parses the incoming NL vendor command data attributes and
8828 * invokes the SME Api and blocks on a completion variable.
8829 * WMA copies required data and invokes callback
8830 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8831 *
8832 * Return: 0 on success; error number otherwise.
8833 */
8834static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8835 struct wireless_dev *wdev,
8836 const void *data, int data_len)
8837{
8838 int ret;
8839
8840 cds_ssr_protect(__func__);
8841 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8842 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008843 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308844
8845 return ret;
8846}
8847
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308848/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308849 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8850 * @wiphy: wiphy structure pointer
8851 * @wdev: Wireless device structure pointer
8852 * @data: Pointer to the data received
8853 * @data_len: Length of @data
8854 *
8855 * This function reads wmi max bus size and fill in the skb with
8856 * NL attributes and send up the NL event.
8857 * Return: 0 on success; errno on failure
8858 */
8859static int
8860__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8861 struct wireless_dev *wdev,
8862 const void *data, int data_len)
8863{
8864 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8865 int ret_val;
8866 struct sk_buff *skb;
8867 uint32_t nl_buf_len;
8868
8869 ENTER();
8870
8871 ret_val = wlan_hdd_validate_context(hdd_ctx);
8872 if (ret_val)
8873 return ret_val;
8874
8875 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8876 hdd_err("Command not allowed in FTM mode");
8877 return -EINVAL;
8878 }
8879
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008880 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308881
8882 nl_buf_len = NLMSG_HDRLEN;
8883 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8884
8885 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8886 if (!skb) {
8887 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8888 return -ENOMEM;
8889 }
8890
8891 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8892 hdd_ctx->wmi_max_len)) {
8893 hdd_err("nla put failure");
8894 goto nla_put_failure;
8895 }
8896
8897 cfg80211_vendor_cmd_reply(skb);
8898
8899 EXIT();
8900
8901 return 0;
8902
8903nla_put_failure:
8904 kfree_skb(skb);
8905 return -EINVAL;
8906}
8907
8908/**
8909 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8910 * @wiphy: wiphy structure pointer
8911 * @wdev: Wireless device structure pointer
8912 * @data: Pointer to the data received
8913 * @data_len: Length of @data
8914 *
8915 * Return: 0 on success; errno on failure
8916 */
8917static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8918 struct wireless_dev *wdev,
8919 const void *data, int data_len)
8920{
8921 int ret;
8922
8923 cds_ssr_protect(__func__);
8924 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8925 cds_ssr_unprotect(__func__);
8926
8927 return ret;
8928}
8929
8930/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308931 *__wlan_hdd_cfg80211_setband() - set band
8932 * @wiphy: Pointer to wireless phy
8933 * @wdev: Pointer to wireless device
8934 * @data: Pointer to data
8935 * @data_len: Length of @data
8936 *
8937 * Return: 0 on success, negative errno on failure
8938 */
8939static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8940 struct wireless_dev *wdev,
8941 const void *data, int data_len)
8942{
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308943 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008944 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308945 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8946 int ret;
8947 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8948 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8949
8950 ENTER();
8951
8952 ret = wlan_hdd_validate_context(hdd_ctx);
8953 if (ret)
8954 return ret;
8955
8956 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8957 hdd_err(FL("Invalid ATTR"));
8958 return -EINVAL;
8959 }
8960
8961 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8962 hdd_err(FL("attr SETBAND_VALUE failed"));
8963 return -EINVAL;
8964 }
8965
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008966 ret = hdd_reg_set_band(dev,
8967 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308968
8969 EXIT();
8970 return ret;
8971}
8972
8973/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308974 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8975 * @adapter: hdd adapter
8976 * @channel: channel number
8977 *
8978 * return: QDF status based on success or failure
8979 */
8980static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8981 int channel, int chan_bw)
8982{
8983 if (QDF_STATUS_SUCCESS !=
8984 wlan_hdd_validate_operation_channel(adapter, channel))
8985 return QDF_STATUS_E_FAILURE;
8986 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8987 channel,
8988 PHY_SINGLE_CHANNEL_CENTERED))) {
8989 hdd_notice("channel %d is in nol", channel);
8990 return -EINVAL;
8991 }
8992
8993 if ((wlansap_is_channel_leaking_in_nol(
8994 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8995 channel, chan_bw))) {
8996 hdd_notice("channel %d is leaking in nol", channel);
8997 return -EINVAL;
8998 }
8999
9000 return 0;
9001
9002}
9003
Kapil Gupta8878ad92017-02-13 11:56:04 +05309004static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
9005 tsap_Config_t *sap_config,
9006 struct hdd_vendor_chan_info *channel_list)
9007{
9008 sap_config->channel = channel_list->pri_ch;
9009
9010 sap_config->ch_params.center_freq_seg0 =
9011 channel_list->vht_seg0_center_ch;
9012 sap_config->ch_params.center_freq_seg1 =
9013 channel_list->vht_seg1_center_ch;
9014
9015 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
9016 sap_config->ch_params.ch_width = channel_list->chan_width;
9017 if (sap_config->channel >= 36)
9018 sap_config->ch_width_orig =
9019 hdd_ctx->config->vhtChannelWidth;
9020 else
9021 sap_config->ch_width_orig =
9022 hdd_ctx->config->nChannelBondingMode24GHz ?
9023 eHT_CHANNEL_WIDTH_40MHZ :
9024 eHT_CHANNEL_WIDTH_20MHZ;
9025
9026 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
9027 sap_config->acs_cfg.ch_width = channel_list->chan_width;
9028 sap_config->acs_cfg.vht_seg0_center_ch =
9029 channel_list->vht_seg0_center_ch;
9030 sap_config->acs_cfg.vht_seg1_center_ch =
9031 channel_list->vht_seg1_center_ch;
9032 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
9033}
9034
9035static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
9036 uint8_t channel_cnt,
9037 struct hdd_vendor_chan_info *channel_list)
9038{
9039 tsap_Config_t *sap_config;
9040 hdd_ap_ctx_t *hdd_ap_ctx;
9041 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9042 QDF_STATUS status = QDF_STATUS_SUCCESS;
9043
9044 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
9045 sap_config = &adapter->sessionCtx.ap.sapConfig;
9046
9047 if (QDF_TIMER_STATE_RUNNING ==
9048 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
9049 ap.vendor_acs_timer)) {
9050 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
9051 }
9052
9053 if (channel_list && channel_list->pri_ch == 0) {
9054 /* Check mode, set default channel */
9055 channel_list->pri_ch = 6;
9056 /*
9057 * sap_select_default_oper_chan(hdd_ctx->hHal,
9058 * sap_config->acs_cfg.hw_mode);
9059 */
9060 }
9061
9062 switch (reason) {
9063 /* SAP init case */
9064 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
9065 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
9066 /* Update Hostapd */
9067 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
9068 break;
9069
9070 /* DFS detected on current channel */
9071 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
9072 wlan_sap_update_next_channel(
9073 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9074 channel_list->pri_ch,
9075 channel_list->chan_width);
9076 status = sme_update_new_channel_event(
9077 WLAN_HDD_GET_HAL_CTX(adapter),
9078 adapter->sessionId);
9079 break;
9080
9081 /* LTE coex event on current channel */
9082 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
9083 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
9084 sap_config->acs_cfg.ch_width = channel_list->chan_width;
9085 hdd_ap_ctx->sapConfig.ch_width_orig =
9086 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08009087 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309088 break;
9089
9090 default:
9091 hdd_info("invalid reason for timer invoke");
9092 }
9093 qdf_mem_free(channel_list);
9094 EXIT();
9095 return status;
9096}
9097
9098/**
9099 * Define short name for vendor channel set config
9100 */
9101#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
9102#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
9103#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
9104#define SET_CHAN_PRIMARY_CHANNEL \
9105 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
9106#define SET_CHAN_SECONDARY_CHANNEL \
9107 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
9108#define SET_CHAN_SEG0_CENTER_CHANNEL \
9109 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
9110#define SET_CHAN_SEG1_CENTER_CHANNEL \
9111 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
9112#define SET_CHAN_CHANNEL_WIDTH \
9113 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
9114#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
9115
9116/**
9117 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
9118 * @channel_list: pointer to hdd_vendor_chan_info
9119 * @reason: channel change reason
9120 * @channel_cnt: channel count
9121 * @data: data
9122 * @data_len: data len
9123 *
9124 * Return: 0 on success, negative errno on failure
9125 */
9126static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
9127 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
9128 const void *data, int data_len)
9129{
9130 int rem, i = 0;
9131 struct nlattr *tb[SET_CHAN_MAX + 1];
9132 struct nlattr *tb2[SET_CHAN_MAX + 1];
9133 struct nlattr *curr_attr;
9134 struct hdd_vendor_chan_info *channel_list;
9135
9136 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
9137 hdd_err("Invalid ATTR");
9138 return -EINVAL;
9139 }
9140
9141 if (tb[SET_CHAN_REASON])
9142 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
9143
9144 if (tb[SET_CHAN_CHANNEL_COUNT]) {
9145 *channel_cnt = nla_get_u8(tb[
9146 SET_CHAN_CHANNEL_COUNT]);
9147 hdd_info("channel count %d", *channel_cnt);
9148 }
9149
9150 if (!(*channel_cnt)) {
9151 hdd_err("channel count is %d", *channel_cnt);
9152 return -EINVAL;
9153 }
9154
9155 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
9156 (*channel_cnt));
9157
9158 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
9159 if (nla_parse(tb2,
9160 SET_CHAN_MAX,
9161 nla_data(curr_attr), nla_len(curr_attr),
9162 NULL)) {
9163 hdd_err("nla_parse failed");
9164 return -EINVAL;
9165 }
9166 /* Parse and Fetch allowed SSID list*/
9167 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
9168 channel_list[i].pri_ch =
9169 nla_get_u8(
9170 tb2[SET_CHAN_PRIMARY_CHANNEL]);
9171 }
9172 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
9173 channel_list[i].ht_sec_ch =
9174 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
9175 }
9176 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
9177 channel_list[i].vht_seg0_center_ch =
9178 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
9179 }
9180 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
9181 channel_list[i].vht_seg1_center_ch =
9182 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
9183 }
9184 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
9185 channel_list[i].chan_width =
9186 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
9187 }
9188 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
9189 i, channel_list[i].pri_ch,
9190 channel_list[i].ht_sec_ch,
9191 channel_list[i].vht_seg0_center_ch,
9192 channel_list[i].vht_seg1_center_ch,
9193 channel_list[i].chan_width);
9194 i++;
9195 if (i > *channel_cnt)
9196 break;
9197 }
9198 *chan_list_ptr = channel_list;
9199
9200 return 0;
9201}
9202
9203/**
9204 * Undef short names for vendor set channel configuration
9205 */
9206#undef SET_CHAN_REASON
9207#undef SET_CHAN_CHANNEL_COUNT
9208#undef SET_CHAN_CHAN_LIST
9209#undef SET_CHAN_PRIMARY_CHANNEL
9210#undef SET_CHAN_SECONDARY_CHANNEL
9211#undef SET_CHAN_SEG0_CENTER_CHANNEL
9212#undef SET_CHAN_SEG1_CENTER_CHANNEL
9213#undef SET_CHAN_CHANNEL_WIDTH
9214#undef SET_CHAN_MAX
9215
9216/**
9217 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9218 * @wiphy: Pointer to wireless phy
9219 * @wdev: Pointer to wireless device
9220 * @data: Pointer to data
9221 * @data_len: Length of @data
9222 *
9223 * Return: 0 on success, negative errno on failure
9224 */
9225static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9226 struct wireless_dev *wdev,
9227 const void *data, int data_len)
9228{
9229 int ret_val;
9230 QDF_STATUS qdf_status;
9231 uint8_t channel_cnt = 0, reason = -1;
9232 struct hdd_vendor_chan_info *channel_list = NULL;
9233 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
9234 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9235
9236 ENTER();
9237
9238 ret_val = wlan_hdd_validate_context(hdd_ctx);
9239 if (ret_val)
9240 return ret_val;
9241
9242 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9243 hdd_err("Command not allowed in FTM mode");
9244 return -EINVAL;
9245 }
9246
9247 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
9248 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
9249 else {
9250 hdd_err("already timeout happened for acs");
9251 return -EINVAL;
9252 }
9253
9254 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
9255 &channel_cnt, data, data_len);
9256 if (ret_val)
9257 return ret_val;
9258
9259 /* Validate channel to be set */
9260 while (channel_cnt && channel_list) {
9261 qdf_status = wlan_hdd_validate_acs_channel(adapter,
9262 channel_list->pri_ch,
9263 channel_list->chan_width);
9264 if (qdf_status == QDF_STATUS_SUCCESS)
9265 break;
9266 channel_cnt--;
9267 channel_list++;
9268 }
9269 if ((channel_cnt <= 0) || !channel_list) {
9270 hdd_err("no available channel/chanlist %p", channel_list);
9271 return -EINVAL;
9272 }
9273
9274 qdf_status = hdd_update_acs_channel(adapter, reason,
9275 channel_cnt, channel_list);
9276 return qdf_status_to_os_return(qdf_status);
9277}
9278
9279/**
9280 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9281 * @wiphy: Pointer to wireless phy
9282 * @wdev: Pointer to wireless device
9283 * @data: Pointer to data
9284 * @data_len: Length of @data
9285 *
9286 * Return: 0 on success, negative errno on failure
9287 */
9288static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9289 struct wireless_dev *wdev,
9290 const void *data, int data_len)
9291{
9292 int ret;
9293
9294 cds_ssr_protect(__func__);
9295 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
9296 data_len);
9297 cds_ssr_protect(__func__);
9298
9299 return ret;
9300}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309301
9302/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309303 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9304 * @wiphy: wiphy structure pointer
9305 * @wdev: Wireless device structure pointer
9306 * @data: Pointer to the data received
9307 * @data_len: Length of @data
9308 *
9309 * Return: 0 on success; errno on failure
9310 */
9311static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9312 struct wireless_dev *wdev,
9313 const void *data, int data_len)
9314{
9315 int ret;
9316
9317 cds_ssr_protect(__func__);
9318 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9319 cds_ssr_unprotect(__func__);
9320
9321 return ret;
9322}
9323
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009324/**
9325 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9326 * @nl80211_value: Vendor command attribute value
9327 * @wmi_value: Pointer to return converted WMI return value
9328 *
9329 * Convert NL80211 vendor command value for SAR limit set to WMI value
9330 * Return: 0 on success, -1 on invalid value
9331 */
9332static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9333 u32 *wmi_value)
9334{
9335 int ret = 0;
9336
9337 switch (nl80211_value) {
9338 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9339 *wmi_value = WMI_SAR_FEATURE_OFF;
9340 break;
9341 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9342 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9343 break;
9344 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9345 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9346 break;
9347 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9348 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9349 break;
9350 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9351 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9352 break;
9353 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9354 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9355 break;
9356 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9357 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9358 break;
9359 default:
9360 ret = -1;
9361 }
9362 return ret;
9363}
9364
9365/**
9366 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9367 * @nl80211_value: Vendor command attribute value
9368 * @wmi_value: Pointer to return converted WMI return value
9369 *
9370 * Convert NL80211 vendor command value for SAR BAND to WMI value
9371 * Return: 0 on success, -1 on invalid value
9372 */
9373static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9374{
9375 int ret = 0;
9376
9377 switch (nl80211_value) {
9378 case NL80211_BAND_2GHZ:
9379 *wmi_value = WMI_SAR_2G_ID;
9380 break;
9381 case NL80211_BAND_5GHZ:
9382 *wmi_value = WMI_SAR_5G_ID;
9383 break;
9384 default:
9385 ret = -1;
9386 }
9387 return ret;
9388}
9389
9390/**
9391 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9392 * @nl80211_value: Vendor command attribute value
9393 * @wmi_value: Pointer to return converted WMI return value
9394 *
9395 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9396 * Return: 0 on success, -1 on invalid value
9397 */
9398static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9399 u32 *wmi_value)
9400{
9401 int ret = 0;
9402
9403 switch (nl80211_value) {
9404 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9405 *wmi_value = WMI_SAR_MOD_CCK;
9406 break;
9407 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9408 *wmi_value = WMI_SAR_MOD_OFDM;
9409 break;
9410 default:
9411 ret = -1;
9412 }
9413 return ret;
9414}
9415
9416
9417/**
9418 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9419 * @wiphy: Pointer to wireless phy
9420 * @wdev: Pointer to wireless device
9421 * @data: Pointer to data
9422 * @data_len: Length of @data
9423 *
9424 * This function is used to setup Specific Absorption Rate limit specs.
9425 *
9426 * Return: 0 on success, negative errno on failure
9427 */
9428static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9429 struct wireless_dev *wdev,
9430 const void *data, int data_len)
9431{
9432 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9433 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9434 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9435 *sar_spec_list;
9436 struct sar_limit_cmd_params sar_limit_cmd = {0};
9437 int ret = -EINVAL, i = 0, rem = 0;
9438
9439 ENTER();
9440
9441 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9442 hdd_err("Command not allowed in FTM mode");
9443 return -EPERM;
9444 }
9445
9446 if (wlan_hdd_validate_context(hdd_ctx))
9447 return -EINVAL;
9448
9449 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9450 data, data_len, NULL)) {
9451 hdd_err("Invalid SAR attributes");
9452 return -EINVAL;
9453 }
9454
9455 /* Vendor command manadates all SAR Specs in single call */
9456 sar_limit_cmd.commit_limits = 1;
9457 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9458 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9459 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9460 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9461 &sar_limit_cmd.sar_enable) < 0) {
9462 hdd_err("Invalid SAR Enable attr");
9463 goto fail;
9464 }
9465 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009466 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009467
9468 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9469 sar_limit_cmd.num_limit_rows = nla_get_u32(
9470 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009471 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009472 sar_limit_cmd.num_limit_rows);
9473 }
9474 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9475 hdd_err("SAR Spec list exceed supported size");
9476 goto fail;
9477 }
9478 if (sar_limit_cmd.num_limit_rows == 0)
9479 goto send_sar_limits;
9480 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9481 struct sar_limit_cmd_row) *
9482 sar_limit_cmd.num_limit_rows);
9483 if (!sar_limit_cmd.sar_limit_row_list) {
9484 ret = -ENOMEM;
9485 goto fail;
9486 }
9487 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9488 hdd_err("Invalid SAR SPECs list");
9489 goto fail;
9490 }
9491
9492 nla_for_each_nested(sar_spec_list,
9493 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9494 if (i == sar_limit_cmd.num_limit_rows) {
9495 hdd_warn("SAR Cmd has excess SPECs in list");
9496 break;
9497 }
9498
9499 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9500 nla_data(sar_spec_list), nla_len(sar_spec_list),
9501 NULL)) {
9502 hdd_err("nla_parse failed for SAR Spec list");
9503 goto fail;
9504 }
9505 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9506 if (sar_spec[
9507 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9508 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9509 nla_get_u32(sar_spec[
9510 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9511 } else {
9512 hdd_err("SAR Spec does not have power limit value");
9513 goto fail;
9514 }
9515
9516 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9517 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9518 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9519 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9520 < 0) {
9521 hdd_err("Invalid SAR Band attr");
9522 goto fail;
9523 }
9524 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9525 WMI_SAR_BAND_ID_VALID_MASK;
9526 }
9527 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9528 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9529 nla_get_u32(sar_spec[
9530 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9531 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9532 WMI_SAR_CHAIN_ID_VALID_MASK;
9533 }
9534 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9535 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9536 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9537 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9538 < 0) {
9539 hdd_err("Invalid SAR Modulation attr");
9540 goto fail;
9541 }
9542 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9543 WMI_SAR_MOD_ID_VALID_MASK;
9544 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009545 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009546 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9547 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9548 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9549 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9550 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9551 i++;
9552 }
9553
9554 if (i < sar_limit_cmd.num_limit_rows) {
9555 hdd_warn("SAR Cmd has less SPECs in list");
9556 sar_limit_cmd.num_limit_rows = i;
9557 }
9558
9559send_sar_limits:
9560 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9561 QDF_STATUS_SUCCESS)
9562 ret = 0;
9563fail:
9564 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9565 return ret;
9566}
9567
9568/**
9569 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9570 * @wiphy: Pointer to wireless phy
9571 * @wdev: Pointer to wireless device
9572 * @data: Pointer to data
9573 * @data_len: Length of @data
9574 *
9575 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9576 *
9577 * Return: 0 on success, negative errno on failure
9578 */
9579static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9580 struct wireless_dev *wdev,
9581 const void *data,
9582 int data_len)
9583{
9584 int ret;
9585
9586 cds_ssr_protect(__func__);
9587 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9588 data_len);
9589 cds_ssr_unprotect(__func__);
9590
9591 return ret;
9592}
9593
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309594static const struct
9595nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9596 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9597 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9598 .len = QDF_MAC_ADDR_SIZE},
9599};
9600
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309601void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9602{
9603 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9604 hdd_adapter_t *adapter;
9605
9606 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9607 if (!adapter) {
9608 hdd_err("adapter NULL");
9609 return;
9610 }
9611
9612 adapter->lfr_fw_status.is_disabled = rso_status->status;
9613 complete(&adapter->lfr_fw_status.disable_lfr_event);
9614}
9615
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309616/**
9617 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9618 * @wiphy: Pointer to wireless phy
9619 * @wdev: Pointer to wireless device
9620 * @data: Pointer to data
9621 * @data_len: Length of @data
9622 *
9623 * This function is used to enable/disable roaming using vendor commands
9624 *
9625 * Return: 0 on success, negative errno on failure
9626 */
9627static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9628 struct wireless_dev *wdev,
9629 const void *data, int data_len)
9630{
9631 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9632 struct net_device *dev = wdev->netdev;
9633 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9634 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309635 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309636 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309637 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309638 unsigned long rc;
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309639 hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309640
9641 ENTER_DEV(dev);
9642
9643 ret = wlan_hdd_validate_context(hdd_ctx);
9644 if (0 != ret)
9645 return ret;
9646
9647 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9648 hdd_err("Command not allowed in FTM mode");
9649 return -EINVAL;
9650 }
9651
9652 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9653 qca_wlan_vendor_attr);
9654 if (ret) {
9655 hdd_err("Invalid ATTR");
9656 return -EINVAL;
9657 }
9658
9659 /* Parse and fetch Enable flag */
9660 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9661 hdd_err("attr enable failed");
9662 return -EINVAL;
9663 }
9664
9665 is_fast_roam_enabled = nla_get_u32(
9666 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009667 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009668 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309669
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009670 if (!adapter->fast_roaming_allowed) {
9671 hdd_err("fast roaming not allowed on %s interface",
9672 adapter->dev->name);
9673 return -EINVAL;
9674 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309675 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309676 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309677 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309678 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309679 if (qdf_status != QDF_STATUS_SUCCESS)
9680 hdd_err("sme_config_fast_roaming failed with status=%d",
9681 qdf_status);
9682 ret = qdf_status_to_os_return(qdf_status);
9683
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309684 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
9685 QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9686
9687 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309688 /*
9689 * wait only for LFR disable in fw as LFR enable
9690 * is always success
9691 */
9692 rc = wait_for_completion_timeout(
9693 &adapter->lfr_fw_status.disable_lfr_event,
9694 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9695 if (!rc) {
9696 hdd_err("Timed out waiting for RSO CMD status");
9697 return -ETIMEDOUT;
9698 }
9699
9700 if (!adapter->lfr_fw_status.is_disabled) {
9701 hdd_err("Roam disable attempt in FW fails");
9702 return -EBUSY;
9703 }
9704 }
9705
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309706 EXIT();
9707 return ret;
9708}
9709
9710/**
9711 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9712 * @wiphy: Pointer to wireless phy
9713 * @wdev: Pointer to wireless device
9714 * @data: Pointer to data
9715 * @data_len: Length of @data
9716 *
9717 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9718 *
9719 * Return: 0 on success, negative errno on failure
9720 */
9721static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9722 struct wireless_dev *wdev,
9723 const void *data, int data_len)
9724{
9725 int ret;
9726
9727 cds_ssr_protect(__func__);
9728 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9729 cds_ssr_unprotect(__func__);
9730
9731 return ret;
9732}
9733
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309734
9735void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9736 uint32_t vdev_id)
9737{
9738 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9739 int status;
9740 hdd_adapter_t *adapter = NULL;
9741 hdd_station_ctx_t *hdd_sta_ctx;
9742
9743 status = wlan_hdd_validate_context(hdd_ctx);
9744 if (status != 0)
9745 return;
9746
9747 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9748 if (adapter == NULL) {
9749 hdd_err("vdev_id %d does not exist with host", vdev_id);
9750 return;
9751 }
9752
9753 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9754 hdd_sta_ctx->conn_info.cca = congestion;
9755 hdd_info("congestion:%d", congestion);
9756}
9757
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309758static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9759 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9760 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9761 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9762 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9763};
9764
9765/**
9766 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9767 * @wiphy: Pointer to wireless phy
9768 * @wdev: Pointer to wireless device
9769 * @data: Pointer to data
9770 * @data_len: Length of @data
9771 *
9772 * Return: 0 on success, negative errno on failure
9773 */
9774static int
9775__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9776 struct wireless_dev *wdev,
9777 const void *data,
9778 int data_len)
9779{
9780 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9781 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9782 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9783 struct nlattr *apth;
9784 int rem;
9785 int ret = 1;
9786 int print_idx = -1;
9787 int module_id = -1;
9788 int bit_mask = -1;
9789 int status;
9790
9791 ENTER();
9792
9793 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9794 hdd_err("Command not allowed in FTM mode");
9795 return -EINVAL;
9796 }
9797
9798 ret = wlan_hdd_validate_context(hdd_ctx);
9799 if (ret != 0)
9800 return -EINVAL;
9801
9802 print_idx = qdf_get_pidx();
9803 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9804 hdd_err("Invalid print controle object index");
9805 return -EINVAL;
9806 }
9807
9808 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9809 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9810 hdd_err("Invalid attr");
9811 return -EINVAL;
9812 }
9813
9814 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9815 hdd_err("attr trace level param failed");
9816 return -EINVAL;
9817 }
9818
9819 nla_for_each_nested(apth,
9820 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9821 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9822 nla_data(apth), nla_len(apth), NULL)) {
9823 hdd_err("Invalid attr");
9824 return -EINVAL;
9825 }
9826
9827 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9828 hdd_err("attr Module ID failed");
9829 return -EINVAL;
9830 }
9831 module_id = nla_get_u32
9832 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9833
9834 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9835 hdd_err("attr Verbose mask failed");
9836 return -EINVAL;
9837 }
9838 bit_mask = nla_get_u32
9839 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9840
9841 status = hdd_qdf_trace_enable(module_id, bit_mask);
9842
9843 if (status != 0)
9844 hdd_err("can not set verbose mask %d for the category %d",
9845 bit_mask, module_id);
9846 }
9847
9848 EXIT();
9849 return ret;
9850}
9851
9852/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309853 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9854 * @wiphy: Pointer to wireless phy
9855 * @wdev: Pointer to wireless device
9856 * @data: Pointer to data
9857 * @data_len: Length of @data
9858 *
9859 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9860 *
9861 * Return: 0 on success, negative errno on failure
9862 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309863
9864static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9865 struct wireless_dev *wdev,
9866 const void *data,
9867 int data_len)
9868{
9869 int ret;
9870
9871 cds_ssr_protect(__func__);
9872 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9873 cds_ssr_unprotect(__func__);
9874
9875 return ret;
9876}
9877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009878const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9879 {
9880 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9881 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9882 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309883 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009884 .doit = is_driver_dfs_capable
9885 },
9886
9887#ifdef WLAN_FEATURE_NAN
9888 {
9889 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9890 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9891 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9892 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9893 .doit = wlan_hdd_cfg80211_nan_request
9894 },
9895#endif
9896
9897#ifdef WLAN_FEATURE_STATS_EXT
9898 {
9899 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9900 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9901 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9902 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9903 .doit = wlan_hdd_cfg80211_stats_ext_request
9904 },
9905#endif
9906#ifdef FEATURE_WLAN_EXTSCAN
9907 {
9908 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9909 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9910 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9911 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9912 .doit = wlan_hdd_cfg80211_extscan_start
9913 },
9914 {
9915 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9916 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9917 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9918 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9919 .doit = wlan_hdd_cfg80211_extscan_stop
9920 },
9921 {
9922 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9923 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9924 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9925 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9926 },
9927 {
9928 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9929 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9930 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9931 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9932 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9933 },
9934 {
9935 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9936 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9937 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9938 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9939 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9940 },
9941 {
9942 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9943 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9944 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9945 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9946 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9947 },
9948 {
9949 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9950 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9951 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9952 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9953 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9954 },
9955 {
9956 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9957 .info.subcmd =
9958 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9959 .flags =
9960 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9961 WIPHY_VENDOR_CMD_NEED_RUNNING,
9962 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9963 },
9964 {
9965 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9966 .info.subcmd =
9967 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9968 .flags =
9969 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9970 WIPHY_VENDOR_CMD_NEED_RUNNING,
9971 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9972 },
9973 {
9974 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9975 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9976 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9977 WIPHY_VENDOR_CMD_NEED_NETDEV |
9978 WIPHY_VENDOR_CMD_NEED_RUNNING,
9979 .doit = wlan_hdd_cfg80211_set_epno_list
9980 },
9981#endif /* FEATURE_WLAN_EXTSCAN */
9982
9983#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9984 {
9985 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9986 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9987 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9988 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9989 .doit = wlan_hdd_cfg80211_ll_stats_clear
9990 },
9991
9992 {
9993 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9994 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9995 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9996 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9997 .doit = wlan_hdd_cfg80211_ll_stats_set
9998 },
9999
10000 {
10001 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10002 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
10003 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10004 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10005 .doit = wlan_hdd_cfg80211_ll_stats_get
10006 },
10007#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
10008#ifdef FEATURE_WLAN_TDLS
10009 {
10010 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10011 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
10012 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10013 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10014 .doit = wlan_hdd_cfg80211_exttdls_enable
10015 },
10016 {
10017 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10018 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
10019 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10020 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10021 .doit = wlan_hdd_cfg80211_exttdls_disable
10022 },
10023 {
10024 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10025 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
10026 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
10027 .doit = wlan_hdd_cfg80211_exttdls_get_status
10028 },
10029#endif
10030 {
10031 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10032 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
10033 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
10034 .doit = wlan_hdd_cfg80211_get_supported_features
10035 },
10036 {
10037 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10038 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010039 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10040 WIPHY_VENDOR_CMD_NEED_NETDEV |
10041 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010042 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
10043 },
10044 {
10045 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10046 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
10047 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +053010048 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010049 },
10050 {
10051 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10052 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
10053 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010054 WIPHY_VENDOR_CMD_NEED_NETDEV |
10055 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010056 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
10057 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070010058 {
10059 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10060 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
10061 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010062 WIPHY_VENDOR_CMD_NEED_NETDEV |
10063 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070010064 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
10065 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010066 {
10067 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +053010068 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
10069 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10070 WIPHY_VENDOR_CMD_NEED_NETDEV |
10071 WIPHY_VENDOR_CMD_NEED_RUNNING,
10072 .doit = hdd_cfg80211_get_station_cmd
10073 },
10074 {
10075 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010076 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
10077 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10078 WIPHY_VENDOR_CMD_NEED_NETDEV |
10079 WIPHY_VENDOR_CMD_NEED_RUNNING,
10080 .doit = wlan_hdd_cfg80211_do_acs
10081 },
10082
10083 {
10084 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10085 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
10086 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10087 WIPHY_VENDOR_CMD_NEED_NETDEV,
10088 .doit = wlan_hdd_cfg80211_get_features
10089 },
10090#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10091 {
10092 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10093 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
10094 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10095 WIPHY_VENDOR_CMD_NEED_NETDEV |
10096 WIPHY_VENDOR_CMD_NEED_RUNNING,
10097 .doit = wlan_hdd_cfg80211_keymgmt_set_key
10098 },
10099#endif
10100#ifdef FEATURE_WLAN_EXTSCAN
10101 {
10102 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10103 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
10104 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10105 WIPHY_VENDOR_CMD_NEED_NETDEV |
10106 WIPHY_VENDOR_CMD_NEED_RUNNING,
10107 .doit = wlan_hdd_cfg80211_set_passpoint_list
10108 },
10109 {
10110 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10111 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
10112 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10113 WIPHY_VENDOR_CMD_NEED_NETDEV |
10114 WIPHY_VENDOR_CMD_NEED_RUNNING,
10115 .doit = wlan_hdd_cfg80211_reset_passpoint_list
10116 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117#endif /* FEATURE_WLAN_EXTSCAN */
10118 {
10119 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10120 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
10121 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10122 WIPHY_VENDOR_CMD_NEED_NETDEV,
10123 .doit = wlan_hdd_cfg80211_get_wifi_info
10124 },
Paul Zhang3a210c52016-12-08 10:18:12 +080010125#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010126 {
10127 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10128 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
10129 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10130 WIPHY_VENDOR_CMD_NEED_NETDEV |
10131 WIPHY_VENDOR_CMD_NEED_RUNNING,
10132 .doit = wlan_hdd_cfg80211_wifi_configuration_set
10133 },
Paul Zhang3a210c52016-12-08 10:18:12 +080010134#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135 {
10136 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10137 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
10138 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010139 WIPHY_VENDOR_CMD_NEED_NETDEV |
10140 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010141 .doit = wlan_hdd_cfg80211_set_ext_roam_params
10142 },
10143 {
10144 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10145 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
10146 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010147 WIPHY_VENDOR_CMD_NEED_NETDEV |
10148 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010149 .doit = wlan_hdd_cfg80211_wifi_logger_start
10150 },
10151 {
10152 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10153 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
10154 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010155 WIPHY_VENDOR_CMD_NEED_NETDEV |
10156 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010157 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
10158 },
10159 {
10160 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10161 .info.subcmd =
10162 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
10163 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10164 WIPHY_VENDOR_CMD_NEED_NETDEV |
10165 WIPHY_VENDOR_CMD_NEED_RUNNING,
10166 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
10167 },
10168 {
10169 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10170 .info.subcmd =
10171 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
10172 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10173 WIPHY_VENDOR_CMD_NEED_NETDEV |
10174 WIPHY_VENDOR_CMD_NEED_RUNNING,
10175 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
10176 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070010177#ifdef WLAN_FEATURE_TSF
10178 {
10179 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10180 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
10181 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10182 WIPHY_VENDOR_CMD_NEED_NETDEV |
10183 WIPHY_VENDOR_CMD_NEED_RUNNING,
10184 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
10185 },
10186#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187#ifdef FEATURE_WLAN_TDLS
10188 {
10189 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10190 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
10191 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10192 WIPHY_VENDOR_CMD_NEED_NETDEV |
10193 WIPHY_VENDOR_CMD_NEED_RUNNING,
10194 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
10195 },
10196#endif
10197#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
10198 {
10199 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10200 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
10201 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10202 WIPHY_VENDOR_CMD_NEED_NETDEV |
10203 WIPHY_VENDOR_CMD_NEED_RUNNING,
10204 .doit = wlan_hdd_cfg80211_offloaded_packets
10205 },
10206#endif
10207 {
10208 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10209 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
10210 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10211 WIPHY_VENDOR_CMD_NEED_NETDEV |
10212 WIPHY_VENDOR_CMD_NEED_RUNNING,
10213 .doit = wlan_hdd_cfg80211_monitor_rssi
10214 },
10215 {
10216 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010217 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
10218 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10219 WIPHY_VENDOR_CMD_NEED_NETDEV |
10220 WIPHY_VENDOR_CMD_NEED_RUNNING,
10221 .doit = wlan_hdd_cfg80211_set_ns_offload
10222 },
10223 {
10224 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010225 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
10226 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10227 WIPHY_VENDOR_CMD_NEED_NETDEV |
10228 WIPHY_VENDOR_CMD_NEED_RUNNING,
10229 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
10230 },
10231#ifdef WLAN_FEATURE_MEMDUMP
10232 {
10233 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10234 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
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_fw_mem_dump
10239 },
10240#endif /* WLAN_FEATURE_MEMDUMP */
10241 {
10242 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10243 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
10244 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10245 WIPHY_VENDOR_CMD_NEED_NETDEV |
10246 WIPHY_VENDOR_CMD_NEED_RUNNING,
10247 .doit = wlan_hdd_cfg80211_vendor_scan
10248 },
10249
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053010250 /* Vendor abort scan */
10251 {
10252 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10253 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
10254 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10255 WIPHY_VENDOR_CMD_NEED_NETDEV |
10256 WIPHY_VENDOR_CMD_NEED_RUNNING,
10257 .doit = wlan_hdd_vendor_abort_scan
10258 },
10259
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010260 /* OCB commands */
10261 {
10262 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10263 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
10264 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10265 WIPHY_VENDOR_CMD_NEED_NETDEV |
10266 WIPHY_VENDOR_CMD_NEED_RUNNING,
10267 .doit = wlan_hdd_cfg80211_ocb_set_config
10268 },
10269 {
10270 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10271 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
10272 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10273 WIPHY_VENDOR_CMD_NEED_NETDEV |
10274 WIPHY_VENDOR_CMD_NEED_RUNNING,
10275 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
10276 },
10277 {
10278 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10279 .info.subcmd =
10280 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
10281 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10282 WIPHY_VENDOR_CMD_NEED_NETDEV |
10283 WIPHY_VENDOR_CMD_NEED_RUNNING,
10284 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
10285 },
10286 {
10287 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10288 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
10289 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10290 WIPHY_VENDOR_CMD_NEED_NETDEV |
10291 WIPHY_VENDOR_CMD_NEED_RUNNING,
10292 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
10293 },
10294 {
10295 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10296 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
10297 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10298 WIPHY_VENDOR_CMD_NEED_NETDEV |
10299 WIPHY_VENDOR_CMD_NEED_RUNNING,
10300 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
10301 },
10302 {
10303 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10304 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
10305 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10306 WIPHY_VENDOR_CMD_NEED_NETDEV |
10307 WIPHY_VENDOR_CMD_NEED_RUNNING,
10308 .doit = wlan_hdd_cfg80211_dcc_get_stats
10309 },
10310 {
10311 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10312 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
10313 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10314 WIPHY_VENDOR_CMD_NEED_NETDEV |
10315 WIPHY_VENDOR_CMD_NEED_RUNNING,
10316 .doit = wlan_hdd_cfg80211_dcc_clear_stats
10317 },
10318 {
10319 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10320 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
10321 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10322 WIPHY_VENDOR_CMD_NEED_NETDEV |
10323 WIPHY_VENDOR_CMD_NEED_RUNNING,
10324 .doit = wlan_hdd_cfg80211_dcc_update_ndl
10325 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010326 {
10327 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10328 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
10329 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10330 WIPHY_VENDOR_CMD_NEED_NETDEV |
10331 WIPHY_VENDOR_CMD_NEED_RUNNING,
10332 .doit = wlan_hdd_cfg80211_get_link_properties
10333 },
Peng Xu278d0122015-09-24 16:34:17 -070010334 {
Peng Xud2220962016-07-11 17:59:17 -070010335 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070010336 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
10337 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10338 WIPHY_VENDOR_CMD_NEED_NETDEV |
10339 WIPHY_VENDOR_CMD_NEED_RUNNING,
10340 .doit = wlan_hdd_cfg80211_set_ota_test
10341 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080010342#ifdef FEATURE_LFR_SUBNET_DETECTION
10343 {
10344 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10345 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
10346 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10347 WIPHY_VENDOR_CMD_NEED_NETDEV |
10348 WIPHY_VENDOR_CMD_NEED_RUNNING,
10349 .doit = wlan_hdd_cfg80211_set_gateway_params
10350 },
10351#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070010352 {
Peng Xud2220962016-07-11 17:59:17 -070010353 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070010354 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
10355 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10356 WIPHY_VENDOR_CMD_NEED_NETDEV |
10357 WIPHY_VENDOR_CMD_NEED_RUNNING,
10358 .doit = wlan_hdd_cfg80211_txpower_scale
10359 },
10360 {
10361 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10362 .info.subcmd =
10363 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
10364 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10365 WIPHY_VENDOR_CMD_NEED_NETDEV |
10366 WIPHY_VENDOR_CMD_NEED_RUNNING,
10367 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
10368 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010369 {
10370 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10371 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
10372 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10373 WIPHY_VENDOR_CMD_NEED_NETDEV |
10374 WIPHY_VENDOR_CMD_NEED_RUNNING,
10375 .doit = wlan_hdd_cfg80211_bpf_offload
10376 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010377 {
10378 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053010379 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
10380 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10381 WIPHY_VENDOR_CMD_NEED_NETDEV |
10382 WIPHY_VENDOR_CMD_NEED_RUNNING,
10383 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10384 },
10385 {
10386 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010387 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10388 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10389 WIPHY_VENDOR_CMD_NEED_NETDEV |
10390 WIPHY_VENDOR_CMD_NEED_RUNNING,
10391 .doit = wlan_hdd_cfg80211_sta_roam_policy
10392 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010393#ifdef FEATURE_WLAN_CH_AVOID
10394 {
10395 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10396 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10397 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10398 WIPHY_VENDOR_CMD_NEED_NETDEV |
10399 WIPHY_VENDOR_CMD_NEED_RUNNING,
10400 .doit = wlan_hdd_cfg80211_avoid_freq
10401 },
10402#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010403 {
10404 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010405 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10406 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10407 WIPHY_VENDOR_CMD_NEED_NETDEV |
10408 WIPHY_VENDOR_CMD_NEED_RUNNING,
10409 .doit = wlan_hdd_cfg80211_sap_configuration_set
10410 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010411 {
Peng Xu4225c152016-07-14 21:18:14 -070010412 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010413 .info.subcmd =
10414 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10415 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10416 WIPHY_VENDOR_CMD_NEED_NETDEV |
10417 WIPHY_VENDOR_CMD_NEED_RUNNING,
10418 .doit = wlan_hdd_cfg80211_p2p_lo_start
10419 },
10420 {
10421 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10422 .info.subcmd =
10423 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10424 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10425 WIPHY_VENDOR_CMD_NEED_NETDEV |
10426 WIPHY_VENDOR_CMD_NEED_RUNNING,
10427 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10428 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010429 {
10430 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10431 .info.subcmd =
10432 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10433 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10434 WIPHY_VENDOR_CMD_NEED_NETDEV |
10435 WIPHY_VENDOR_CMD_NEED_RUNNING,
10436 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10437 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010438#ifdef WLAN_FEATURE_NAN_DATAPATH
10439 {
10440 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10441 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10442 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10443 WIPHY_VENDOR_CMD_NEED_NETDEV |
10444 WIPHY_VENDOR_CMD_NEED_RUNNING,
10445 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10446 },
10447#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010448 {
10449 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10450 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10451 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10452 WIPHY_VENDOR_CMD_NEED_NETDEV |
10453 WIPHY_VENDOR_CMD_NEED_RUNNING,
10454 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10455 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010456 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010457 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10458 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10459 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10460 WIPHY_VENDOR_CMD_NEED_NETDEV |
10461 WIPHY_VENDOR_CMD_NEED_RUNNING,
10462 .doit = wlan_hdd_cfg80211_get_bus_size
10463 },
10464 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010465 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10466 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10467 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10468 WIPHY_VENDOR_CMD_NEED_NETDEV |
10469 WIPHY_VENDOR_CMD_NEED_RUNNING,
10470 .doit = wlan_hdd_cfg80211_update_vendor_channel
10471 },
10472 {
bingsd09dea32017-03-17 10:08:26 +080010473 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010474 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10475 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10476 WIPHY_VENDOR_CMD_NEED_NETDEV |
10477 WIPHY_VENDOR_CMD_NEED_RUNNING,
10478 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010479 },
10480 {
10481 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10482 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10483 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10484 WIPHY_VENDOR_CMD_NEED_NETDEV |
10485 WIPHY_VENDOR_CMD_NEED_RUNNING,
10486 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010487 },
10488#ifdef WLAN_FEATURE_DISA
10489 {
10490 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10491 .info.subcmd =
10492 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10493 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10494 WIPHY_VENDOR_CMD_NEED_NETDEV |
10495 WIPHY_VENDOR_CMD_NEED_RUNNING,
10496 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10497 },
10498#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010499#ifdef FEATURE_WLAN_TDLS
10500 {
10501 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10502 .info.subcmd =
10503 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10504 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10505 WIPHY_VENDOR_CMD_NEED_NETDEV |
10506 WIPHY_VENDOR_CMD_NEED_RUNNING,
10507 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010508 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010509#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010510 {
10511 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10512 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10513 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10514 WIPHY_VENDOR_CMD_NEED_RUNNING,
10515 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10516 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010517 {
10518 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10519 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10520 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10521 WIPHY_VENDOR_CMD_NEED_NETDEV |
10522 WIPHY_VENDOR_CMD_NEED_RUNNING,
10523 .doit = wlan_hdd_cfg80211_set_trace_level
10524 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080010525 {
10526 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10527 .info.subcmd =
10528 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
10529 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10530 WIPHY_VENDOR_CMD_NEED_NETDEV |
10531 WIPHY_VENDOR_CMD_NEED_RUNNING,
10532 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
10533 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010534
Paul Zhang3a210c52016-12-08 10:18:12 +080010535#ifdef WLAN_UMAC_CONVERGENCE
10536 COMMON_VENDOR_COMMANDS
10537#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010538 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010539};
10540
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010541#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10542 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10543 defined(FEATURE_WLAN_SCAN_PNO)
10544/**
10545 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10546 * @wiphy: pointer to wiphy
10547 * @config: pointer to config
10548 *
10549 * Return: None
10550 */
10551static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10552 struct hdd_config *config)
10553{
10554 if (config->configPNOScanSupport) {
10555 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010556 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10557 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010558 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010559 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010560 if (config->max_sched_scan_plan_interval)
10561 wiphy->max_sched_scan_plan_interval =
10562 config->max_sched_scan_plan_interval;
10563 if (config->max_sched_scan_plan_iterations)
10564 wiphy->max_sched_scan_plan_iterations =
10565 config->max_sched_scan_plan_iterations;
10566 }
10567}
10568#else
10569static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10570 struct hdd_config *config)
10571{
10572}
10573#endif
10574
10575
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010576/**
10577 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10578 * @priv_size: Size of the hdd context.
10579 *
10580 * Allocate wiphy context and hdd context.
10581 *
10582 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010583 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010584hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010585{
10586 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010587 hdd_context_t *hdd_ctx;
10588
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010589 ENTER();
10590
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010591 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10592
10593 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010594 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010595 return NULL;
10596 }
10597
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010598 hdd_ctx = wiphy_priv(wiphy);
10599
10600 hdd_ctx->wiphy = wiphy;
10601
10602 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010603}
10604
10605/*
10606 * FUNCTION: wlan_hdd_cfg80211_update_band
10607 * This function is called from the supplicant through a
10608 * private ioctl to change the band value
10609 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010610int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10611 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010612{
10613 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010614 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010615
10616 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010617 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010618
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010619 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010620 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010621
10622 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10623 struct ieee80211_supported_band *band = wiphy->bands[i];
10624
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010625 channelEnabledState = wlan_reg_get_channel_state(
10626 hdd_ctx->hdd_pdev,
10627 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010628
Dustin Browna30892e2016-10-12 17:28:36 -070010629 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010630 /* 5G only */
10631#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10632 /* Enable Social channels for P2P */
10633 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10634 (band->channels[j].center_freq)
10635 && CHANNEL_STATE_ENABLE ==
10636 channelEnabledState)
10637 band->channels[j].flags &=
10638 ~IEEE80211_CHAN_DISABLED;
10639 else
10640#endif
10641 band->channels[j].flags |=
10642 IEEE80211_CHAN_DISABLED;
10643 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010644 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010645 eCSR_BAND_24 == eBand) {
10646 /* 2G only */
10647 band->channels[j].flags |=
10648 IEEE80211_CHAN_DISABLED;
10649 continue;
10650 }
10651
Amar Singhal6842e8f2016-02-23 16:30:32 -080010652 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010653 band->channels[j].flags &=
10654 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010655 }
10656 }
10657 return 0;
10658}
10659
Peng Xuacfdda12017-02-06 16:15:38 -080010660#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010661/*
10662 * FUNCTION: wlan_hdd_cfg80211_init
10663 * This function is called by hdd_wlan_startup()
10664 * during initialization.
10665 * This function is used to initialize and register wiphy structure.
10666 */
10667int wlan_hdd_cfg80211_init(struct device *dev,
10668 struct wiphy *wiphy, struct hdd_config *pCfg)
10669{
10670 int i, j;
10671 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10672
10673 ENTER();
10674
10675 /* Now bind the underlying wlan device with wiphy */
10676 set_wiphy_dev(wiphy, dev);
10677
10678 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010680 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10681 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10682 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10683#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10684 | WIPHY_FLAG_4ADDR_STATION
10685#endif
10686 | WIPHY_FLAG_OFFCHAN_TX;
10687
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010688#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10689 wiphy->wowlan = &wowlan_support_cfg80211_init;
10690#else
10691 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10692 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10693 wiphy->wowlan.pattern_min_len = 1;
10694 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10695#endif
10696
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010697 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010698#ifdef FEATURE_WLAN_ESE
10699 || pCfg->isEseIniFeatureEnabled
10700#endif
10701 ) {
10702 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10703 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704#ifdef FEATURE_WLAN_TDLS
10705 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10706 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10707#endif
10708
10709 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10710
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010711#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10712 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10713#endif
10714
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010715 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010716
10717#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010718 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010719#endif
10720
10721 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010722 * driver can still register regulatory callback and
10723 * it will get regulatory settings in wiphy->band[], but
10724 * driver need to determine what to do with both
10725 * regulatory settings
10726 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010727
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010728#if defined QCA_WIFI_FTM
10729}
10730#endif
10731
10732 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10733
10734 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10735
10736 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10737
Arun Khandavallifae92942016-08-01 13:31:08 +053010738 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10739 | BIT(NL80211_IFTYPE_ADHOC)
10740 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10741 | BIT(NL80211_IFTYPE_P2P_GO)
10742 | BIT(NL80211_IFTYPE_AP)
10743 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010744
Arun Khandavallifae92942016-08-01 13:31:08 +053010745 if (pCfg->advertiseConcurrentOperation) {
10746 if (pCfg->enableMCC) {
10747 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010748
Arun Khandavallifae92942016-08-01 13:31:08 +053010749 for (i = 0;
10750 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10751 i++) {
10752 if (!pCfg->allowMCCGODiffBI)
10753 wlan_hdd_iface_combination[i].
10754 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010755 }
10756 }
10757 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010758 ARRAY_SIZE(wlan_hdd_iface_combination);
10759 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760 }
10761
10762 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010763 * on ini values
10764 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010765 if (!pCfg->ShortGI20MhzEnable) {
10766 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10767 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010768 }
10769
10770 if (!pCfg->ShortGI40MhzEnable) {
10771 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10772 }
10773
10774 if (!pCfg->nChannelBondingMode5GHz) {
10775 wlan_hdd_band_5_ghz.ht_cap.cap &=
10776 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10777 }
10778
Abhishek Singhf512bf32016-05-04 16:47:46 +053010779 /*
10780 * In case of static linked driver at the time of driver unload,
10781 * module exit doesn't happens. Module cleanup helps in cleaning
10782 * of static memory.
10783 * If driver load happens statically, at the time of driver unload,
10784 * wiphy flags don't get reset because of static memory.
10785 * It's better not to store channel in static memory.
10786 */
Dustin Browna30892e2016-10-12 17:28:36 -070010787 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10788 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010789 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010790 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010791 hdd_err("Not enough memory to allocate channels");
10792 return -ENOMEM;
10793 }
Dustin Browna30892e2016-10-12 17:28:36 -070010794 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010795 &hdd_channels_2_4_ghz[0],
10796 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010797 if ((hdd_is_5g_supported(pHddCtx)) &&
10798 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10799 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10800 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10801 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010802 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10803 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010804 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010805 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010806 hdd_err("Not enough memory to allocate channels");
10807 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010808 bands[NL80211_BAND_2GHZ]->channels);
10809 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010810 return -ENOMEM;
10811 }
Dustin Browna30892e2016-10-12 17:28:36 -070010812 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010813 &hdd_channels_5_ghz[0],
10814 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010815 }
10816
Dustin Browna30892e2016-10-12 17:28:36 -070010817 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010818
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010819 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010820 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010821
10822 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10823 struct ieee80211_supported_band *band = wiphy->bands[i];
10824
Dustin Browna30892e2016-10-12 17:28:36 -070010825 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010826 eCSR_BAND_5G == pCfg->nBandCapability) {
10827 /* 5G only */
10828#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10829 /* Enable social channels for P2P */
10830 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10831 (band->channels[j].center_freq))
10832 band->channels[j].flags &=
10833 ~IEEE80211_CHAN_DISABLED;
10834 else
10835#endif
10836 band->channels[j].flags |=
10837 IEEE80211_CHAN_DISABLED;
10838 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010839 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010840 eCSR_BAND_24 == pCfg->nBandCapability) {
10841 /* 2G only */
10842 band->channels[j].flags |=
10843 IEEE80211_CHAN_DISABLED;
10844 continue;
10845 }
10846 }
10847 }
10848 /*Initialise the supported cipher suite details */
10849 wiphy->cipher_suites = hdd_cipher_suites;
10850 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10851
10852 /*signal strength in mBm (100*dBm) */
10853 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10854 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10855
Anurag Chouhan6d760662016-02-20 16:05:43 +053010856 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010857 wiphy->n_vendor_commands =
10858 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10859 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10860
10861 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10862 wiphy->n_vendor_events =
10863 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10864 }
10865
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010866 if (pCfg->enableDFSMasterCap) {
10867 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10868 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010869
10870 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10871
10872#ifdef QCA_HT_2040_COEX
10873 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10874#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010875 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010876
10877#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10878 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10879 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10880 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10881 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10882#endif
10883
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010884 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010885 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887 EXIT();
10888 return 0;
10889}
10890
Abhishek Singhf512bf32016-05-04 16:47:46 +053010891/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010892 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10893 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010894 *
10895 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010896 * memory allocated in wlan_hdd_cfg80211_init also
10897 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010898 *
10899 * Return: void
10900 */
10901void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10902{
10903 int i;
10904
Dustin Browna30892e2016-10-12 17:28:36 -070010905 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010906 if (NULL != wiphy->bands[i] &&
10907 (NULL != wiphy->bands[i]->channels)) {
10908 qdf_mem_free(wiphy->bands[i]->channels);
10909 wiphy->bands[i]->channels = NULL;
10910 }
10911 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010912
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010913 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010914}
10915
Yingying Tang80e15f32016-09-27 18:23:01 +080010916/**
10917 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10918 * @hdd_ctx: HDD context
10919 *
10920 * this function will update capabilities for supported bands
10921 *
10922 * Return: void
10923 */
10924static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10925{
10926 uint32_t val32;
10927 uint16_t val16;
10928 tSirMacHTCapabilityInfo *ht_cap_info;
10929 QDF_STATUS status;
10930
10931 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10932 if (QDF_STATUS_SUCCESS != status) {
10933 hdd_err("could not get HT capability info");
10934 val32 = 0;
10935 }
10936 val16 = (uint16_t)val32;
10937 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10938
10939 if (ht_cap_info->txSTBC == true) {
10940 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10941 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10942 IEEE80211_HT_CAP_TX_STBC;
10943 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10944 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10945 IEEE80211_HT_CAP_TX_STBC;
10946 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010947
10948 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10949 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10950 vht_cap.vht_supported = 0;
10951 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10952 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10953 vht_cap.vht_supported = 0;
10954 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10955 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010956}
10957
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010958/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010959 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 * initialization. In wlan_hdd_cfg80211_init, only the
10961 * default values will be initialized. The final initialization
10962 * of all required members can be done here.
10963 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010964void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010965{
Yingying Tang80e15f32016-09-27 18:23:01 +080010966 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10967
10968 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010969}
10970
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010971/**
10972 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10973 * @cfg: hdd cfg
10974 *
10975 * this function update 11n mode in hdd cfg
10976 *
10977 * Return: void
10978 */
10979void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10980{
10981 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010982 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010983 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010984 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010985 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10986 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10987 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10988 cfg->sap_p2p_11ac_override = 0;
10989 }
10990 }
10991}
10992
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993/* In this function we are registering wiphy. */
10994int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10995{
10996 ENTER();
10997 /* Register our wiphy dev with cfg80211 */
10998 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010999 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011000 return -EIO;
11001 }
11002
11003 EXIT();
11004 return 0;
11005}
11006
11007/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011008 * HDD function to update wiphy capability based on target offload status.
11009 *
11010 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
11011 * capability even before downloading firmware to the target. In discrete
11012 * case, host will get know certain offload capability (say sched_scan
11013 * caps) only after downloading firmware to the target and target boots up.
11014 * This function is used to override setting done in wlan_hdd_cfg80211_init()
11015 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011016 */
11017void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
11018{
11019#ifdef FEATURE_WLAN_SCAN_PNO
11020 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
11021 struct hdd_config *pCfg = pHddCtx->config;
11022
11023 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
11024 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011025 * have PNO support.
11026 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011027 if (!pCfg->PnoOffload) {
11028 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
11029 wiphy->max_sched_scan_ssids = 0;
11030 wiphy->max_match_sets = 0;
11031 wiphy->max_sched_scan_ie_len = 0;
11032 }
11033#endif
11034}
11035
11036/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011037#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
11038
Wu Gao84d120c2017-03-24 18:46:00 +080011039void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
11040{
11041 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11042 /* Register for all P2P action, public action etc frames */
11043 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11044
11045 ENTER();
11046
11047 /* Register frame indication call back */
11048 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
11049
11050 /* Register for p2p ack indication */
11051 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
11052
11053 /* Right now we are registering these frame when driver is getting
11054 * initialized. Once we will move to 2.6.37 kernel, in which we have
11055 * frame register ops, we will move this code as a part of that
11056 */
11057
11058 /* GAS Initial Request */
11059 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11060 (uint8_t *) GAS_INITIAL_REQ,
11061 GAS_INITIAL_REQ_SIZE);
11062
11063 /* GAS Initial Response */
11064 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11065 (uint8_t *) GAS_INITIAL_RSP,
11066 GAS_INITIAL_RSP_SIZE);
11067
11068 /* GAS Comeback Request */
11069 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11070 (uint8_t *) GAS_COMEBACK_REQ,
11071 GAS_COMEBACK_REQ_SIZE);
11072
11073 /* GAS Comeback Response */
11074 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11075 (uint8_t *) GAS_COMEBACK_RSP,
11076 GAS_COMEBACK_RSP_SIZE);
11077
11078 /* WNM BSS Transition Request frame */
11079 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11080 (uint8_t *) WNM_BSS_ACTION_FRAME,
11081 WNM_BSS_ACTION_FRAME_SIZE);
11082
11083 /* WNM-Notification */
11084 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
11085 (uint8_t *) WNM_NOTIFICATION_FRAME,
11086 WNM_NOTIFICATION_FRAME_SIZE);
11087}
11088#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011089void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
11090{
11091 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11092 /* Register for all P2P action, public action etc frames */
11093 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11094
11095 ENTER();
11096
Abhishek Singh7996eb72015-12-30 17:24:02 +053011097 /* Register frame indication call back */
11098 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
11099
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053011100 /* Register for p2p ack indication */
11101 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
11102
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011103 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011104 * initialized. Once we will move to 2.6.37 kernel, in which we have
11105 * frame register ops, we will move this code as a part of that
11106 */
11107
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011108 /* GAS Initial Request */
11109 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11110 (uint8_t *) GAS_INITIAL_REQ,
11111 GAS_INITIAL_REQ_SIZE);
11112
11113 /* GAS Initial Response */
11114 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11115 (uint8_t *) GAS_INITIAL_RSP,
11116 GAS_INITIAL_RSP_SIZE);
11117
11118 /* GAS Comeback Request */
11119 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11120 (uint8_t *) GAS_COMEBACK_REQ,
11121 GAS_COMEBACK_REQ_SIZE);
11122
11123 /* GAS Comeback Response */
11124 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11125 (uint8_t *) GAS_COMEBACK_RSP,
11126 GAS_COMEBACK_RSP_SIZE);
11127
11128 /* P2P Public Action */
11129 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11130 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11131 P2P_PUBLIC_ACTION_FRAME_SIZE);
11132
11133 /* P2P Action */
11134 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11135 (uint8_t *) P2P_ACTION_FRAME,
11136 P2P_ACTION_FRAME_SIZE);
11137
11138 /* WNM BSS Transition Request frame */
11139 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11140 (uint8_t *) WNM_BSS_ACTION_FRAME,
11141 WNM_BSS_ACTION_FRAME_SIZE);
11142
11143 /* WNM-Notification */
11144 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
11145 (uint8_t *) WNM_NOTIFICATION_FRAME,
11146 WNM_NOTIFICATION_FRAME_SIZE);
11147}
Wu Gao84d120c2017-03-24 18:46:00 +080011148#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011149
11150void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
11151{
11152 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11153 /* Register for all P2P action, public action etc frames */
11154 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11155
11156 ENTER();
11157
11158 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011159 * initialized. Once we will move to 2.6.37 kernel, in which we have
11160 * frame register ops, we will move this code as a part of that
11161 */
11162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011163 /* GAS Initial Request */
11164
11165 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11166 (uint8_t *) GAS_INITIAL_REQ,
11167 GAS_INITIAL_REQ_SIZE);
11168
11169 /* GAS Initial Response */
11170 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11171 (uint8_t *) GAS_INITIAL_RSP,
11172 GAS_INITIAL_RSP_SIZE);
11173
11174 /* GAS Comeback Request */
11175 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11176 (uint8_t *) GAS_COMEBACK_REQ,
11177 GAS_COMEBACK_REQ_SIZE);
11178
11179 /* GAS Comeback Response */
11180 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11181 (uint8_t *) GAS_COMEBACK_RSP,
11182 GAS_COMEBACK_RSP_SIZE);
11183
11184 /* P2P Public Action */
11185 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11186 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11187 P2P_PUBLIC_ACTION_FRAME_SIZE);
11188
11189 /* P2P Action */
11190 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11191 (uint8_t *) P2P_ACTION_FRAME,
11192 P2P_ACTION_FRAME_SIZE);
11193
11194 /* WNM-Notification */
11195 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
11196 (uint8_t *) WNM_NOTIFICATION_FRAME,
11197 WNM_NOTIFICATION_FRAME_SIZE);
11198}
11199
11200#ifdef FEATURE_WLAN_WAPI
11201void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
11202 const uint8_t *mac_addr, const uint8_t *key,
11203 int key_Len)
11204{
11205 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11206 tCsrRoamSetKey setKey;
11207 bool isConnected = true;
11208 int status = 0;
11209 uint32_t roamId = 0xFF;
11210 uint8_t *pKeyPtr = NULL;
11211 int n = 0;
11212
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011213 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011214 hdd_device_mode_to_string(pAdapter->device_mode),
11215 pAdapter->device_mode);
11216
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011217 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011218 setKey.keyId = key_index; /* Store Key ID */
11219 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
11220 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
11221 setKey.paeRole = 0; /* the PAE role */
11222 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053011223 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011224 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011225 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011226 }
11227 setKey.keyLength = key_Len;
11228 pKeyPtr = setKey.Key;
11229 memcpy(pKeyPtr, key, key_Len);
11230
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011231 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011232 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011233 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070011234 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011235
11236 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11237 if (isConnected) {
11238 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11239 pAdapter->sessionId, &setKey, &roamId);
11240 }
11241 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011242 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011243 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
11244 }
11245}
11246#endif /* FEATURE_WLAN_WAPI */
11247
11248uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
11249 uint8_t eid)
11250{
11251 int left = length;
11252 uint8_t *ptr = (uint8_t *)ies_ptr;
11253 uint8_t elem_id, elem_len;
11254
11255 while (left >= 2) {
11256 elem_id = ptr[0];
11257 elem_len = ptr[1];
11258 left -= 2;
11259 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011260 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011261 eid, elem_len, left);
11262 return NULL;
11263 }
11264 if (elem_id == eid) {
11265 return ptr;
11266 }
11267
11268 left -= elem_len;
11269 ptr += (elem_len + 2);
11270 }
11271 return NULL;
11272}
11273
Krunal Soni364e0872017-05-10 21:24:34 -070011274bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
11275{
11276 uint8_t *vendor_ie;
11277
11278 if (length < 2) {
11279 hdd_debug("bss size is less than expected");
11280 return true;
11281 }
11282 if (!ies) {
11283 hdd_debug("invalid IE pointer");
11284 return true;
11285 }
11286 vendor_ie = wlan_hdd_get_vendor_oui_ie_ptr(VENDOR1_AP_OUI_TYPE,
11287 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
11288 if (vendor_ie) {
11289 hdd_debug("AP can't support immediate powersave. defer it");
11290 return false;
11291 }
11292 return true;
11293}
11294
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011295/*
11296 * FUNCTION: wlan_hdd_validate_operation_channel
11297 * called by wlan_hdd_cfg80211_start_bss() and
11298 * wlan_hdd_set_channel()
11299 * This function validates whether given channel is part of valid
11300 * channel list.
11301 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011302QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011303 int channel)
11304{
11305
11306 uint32_t num_ch = 0;
11307 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11308 u32 indx = 0;
11309 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11310 uint8_t fValidChannel = false, count = 0;
11311 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
11312
11313 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11314
11315 if (hdd_pConfig_ini->sapAllowAllChannel) {
11316 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080011317 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011318 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011319 fValidChannel = true;
11320 break;
11321 }
11322 }
11323 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011324 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011325 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011326 }
11327 } else {
11328 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
11329 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011330 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011331 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011332 }
11333 for (indx = 0; indx < num_ch; indx++) {
11334 if (channel == valid_ch[indx]) {
11335 break;
11336 }
11337 }
11338
11339 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011340 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011341 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011342 }
11343 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011344 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011345
11346}
11347
11348#ifdef DHCP_SERVER_OFFLOAD
11349static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
11350{
11351 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
11352 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
11353 uint8_t numEntries = 0;
11354 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
11355 uint8_t num;
11356 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011357 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011358 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070011359 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011360 return;
11361 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011362 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
11363 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
11364 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
11365 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
11366 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
11367 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011368 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011369 goto end;
11370 }
11371 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011372 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011373 goto end;
11374 }
11375 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011376 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377 goto end;
11378 }
11379 for (num = 0; num < numEntries; num++) {
11380 temp = srv_ip[num];
11381 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
11382 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011383 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011384 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011385 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011386 goto end;
11387 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011388 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011389end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011390 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011391 return;
11392}
11393#endif /* DHCP_SERVER_OFFLOAD */
11394
11395static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11396 struct net_device *dev,
11397 struct bss_parameters *params)
11398{
11399 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11400 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11401 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011402 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011403
11404 ENTER();
11405
Anurag Chouhan6d760662016-02-20 16:05:43 +053011406 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011407 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011408 return -EINVAL;
11409 }
11410
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011411 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11412 hdd_err("invalid session id: %d", pAdapter->sessionId);
11413 return -EINVAL;
11414 }
11415
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011416 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011417 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11418 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011419 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011420 hdd_device_mode_to_string(pAdapter->device_mode),
11421 pAdapter->device_mode, params->ap_isolate);
11422
11423 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11424 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011425 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011426 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011427
Krunal Sonib4326f22016-03-10 13:05:51 -080011428 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11429 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011430 return -EOPNOTSUPP;
11431 }
11432
11433 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011434 * want to update this parameter
11435 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011436 if (-1 != params->ap_isolate) {
11437 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11438 !!params->ap_isolate;
11439
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011440 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011441 pAdapter->sessionId,
11442 pAdapter->sessionCtx.
11443 ap.
11444 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011445 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011446 ret = -EINVAL;
11447 }
11448 }
11449
11450 EXIT();
11451 return ret;
11452}
11453
Krunal Soni8c37e322016-02-03 16:08:37 -080011454/**
11455 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11456 * @ndev: pointer to net device provided by supplicant
11457 * @type: type of the interface, upper layer wanted to change
11458 *
11459 * Upper layer provides the new interface mode that needs to be changed
11460 * for given net device
11461 *
11462 * Return: success or failure in terms of integer value
11463 */
11464static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011465 enum nl80211_iftype type)
11466{
Krunal Soni8c37e322016-02-03 16:08:37 -080011467 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11468 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11469 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011470 hdd_wext_state_t *wext;
11471 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011472 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011473
11474 ENTER();
11475
Krunal Soni8c37e322016-02-03 16:08:37 -080011476 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011477 hdd_warn("ACS is in progress, don't change iface!");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011478 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011479 }
11480
11481 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011482 hdd_stop_adapter(hdd_ctx, adapter, true);
11483 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011484 wdev->iftype = type;
11485 /*Check for sub-string p2p to confirm its a p2p interface */
11486 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011487 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011488 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011489 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011490 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011491 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011492 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011493 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011494 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011495 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011496 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011497 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11498 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011499 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11500 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011501 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011502 adapter->scan_info.scanAddIE.length;
11503 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011504 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011505 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11506 wext->roamProfile.phyMode =
11507 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11508 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011509 EXIT();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011510
11511 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011512}
11513
11514static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11515 struct net_device *dev,
11516 struct bss_parameters *params)
11517{
11518 int ret;
11519
11520 cds_ssr_protect(__func__);
11521 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11522 cds_ssr_unprotect(__func__);
11523
11524 return ret;
11525}
11526
11527/* FUNCTION: wlan_hdd_change_country_code_cd
11528 * to wait for contry code completion
11529 */
11530void *wlan_hdd_change_country_code_cb(void *pAdapter)
11531{
11532 hdd_adapter_t *call_back_pAdapter = pAdapter;
11533 complete(&call_back_pAdapter->change_country_code);
11534 return NULL;
11535}
11536
Rajeev Kumar98edb772016-01-19 12:42:19 -080011537/**
11538 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11539 * @wiphy: Pointer to the wiphy structure
11540 * @ndev: Pointer to the net device
11541 * @type: Interface type
11542 * @flags: Flags for change interface
11543 * @params: Pointer to change interface parameters
11544 *
11545 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011546 */
11547static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11548 struct net_device *ndev,
11549 enum nl80211_iftype type,
11550 u32 *flags,
11551 struct vif_params *params)
11552{
11553 struct wireless_dev *wdev;
11554 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11555 hdd_context_t *pHddCtx;
11556 tCsrRoamProfile *pRoamProfile = NULL;
11557 eCsrRoamBssType LastBSSType;
11558 struct hdd_config *pConfig = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011559 int status;
11560
11561 ENTER();
11562
Anurag Chouhan6d760662016-02-20 16:05:43 +053011563 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011564 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011565 return -EINVAL;
11566 }
11567
11568 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11569 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011570 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011571 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011572
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011573 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011574 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11575 pAdapter->sessionId, type));
11576
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011577 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011578 pAdapter->device_mode, type);
11579
Arun Khandavallifae92942016-08-01 13:31:08 +053011580 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11581 if (status) {
11582 hdd_err("Failed to start modules");
11583 return -EINVAL;
11584 }
11585
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011586 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11588 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011589 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011590 return -EINVAL;
11591 }
11592
11593 pConfig = pHddCtx->config;
11594 wdev = ndev->ieee80211_ptr;
11595
11596 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011597 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11598 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011599
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011600 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011601 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011602 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11603 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11604 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11605 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011606 hdd_wext_state_t *pWextState =
11607 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11608
11609 pRoamProfile = &pWextState->roamProfile;
11610 LastBSSType = pRoamProfile->BSSType;
11611
11612 switch (type) {
11613 case NL80211_IFTYPE_STATION:
11614 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011615 case NL80211_IFTYPE_ADHOC:
11616 if (type == NL80211_IFTYPE_ADHOC) {
11617 wlan_hdd_tdls_exit(pAdapter);
11618 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011619 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011620 }
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011621 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
Krunal Soni8c37e322016-02-03 16:08:37 -080011622 type);
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011623 if (status) {
11624 hdd_err("Failed to change iface to new mode:%d status %d",
11625 type, status);
11626 return status;
11627 }
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011628 if (hdd_start_adapter(pAdapter)) {
11629 hdd_err("Failed to start adapter :%d",
11630 pAdapter->device_mode);
11631 return -EINVAL;
11632 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011633 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011634 case NL80211_IFTYPE_AP:
11635 case NL80211_IFTYPE_P2P_GO:
11636 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011637 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638 (type ==
11639 NL80211_IFTYPE_AP) ? "SoftAP" :
11640 "P2pGo");
11641
11642 /* Cancel any remain on channel for GO mode */
11643 if (NL80211_IFTYPE_P2P_GO == type) {
11644 wlan_hdd_cancel_existing_remain_on_channel
11645 (pAdapter);
11646 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011647
Arun Khandavallifae92942016-08-01 13:31:08 +053011648 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011649 /* De-init the adapter */
11650 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11651 memset(&pAdapter->sessionCtx, 0,
11652 sizeof(pAdapter->sessionCtx));
11653 pAdapter->device_mode =
11654 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011655 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11656 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011657
11658 /*
11659 * Fw will take care incase of concurrency
11660 */
11661
Krunal Sonib4326f22016-03-10 13:05:51 -080011662 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011663 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011664 /* To meet Android requirements create
11665 * a randomized MAC address of the
11666 * form 02:1A:11:Fx:xx:xx
11667 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011668 get_random_bytes(&ndev->dev_addr[3], 3);
11669 ndev->dev_addr[0] = 0x02;
11670 ndev->dev_addr[1] = 0x1A;
11671 ndev->dev_addr[2] = 0x11;
11672 ndev->dev_addr[3] |= 0xF0;
11673 memcpy(pAdapter->macAddressCurrent.
11674 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011675 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011676 pr_info("wlan: Generated HotSpot BSSID "
11677 MAC_ADDRESS_STR "\n",
11678 MAC_ADDR_ARRAY(ndev->dev_addr));
11679 }
11680
11681 hdd_set_ap_ops(pAdapter->dev);
11682
Arun Khandavallifae92942016-08-01 13:31:08 +053011683 if (hdd_start_adapter(pAdapter)) {
11684 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011685 return -EINVAL;
11686 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687 /* Interface type changed update in wiphy structure */
11688 if (wdev) {
11689 wdev->iftype = type;
11690 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011691 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011692 return -EINVAL;
11693 }
11694 goto done;
11695 }
11696
11697 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011698 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011699 return -EOPNOTSUPP;
11700 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011701 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11702 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011703 switch (type) {
11704 case NL80211_IFTYPE_STATION:
11705 case NL80211_IFTYPE_P2P_CLIENT:
11706 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011707 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11708 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011709 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011710 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011711 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011712 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011713 pAdapter->device_mode);
11714 return -EINVAL;
11715 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011716 goto done;
11717
11718 case NL80211_IFTYPE_AP:
11719 case NL80211_IFTYPE_P2P_GO:
11720 wdev->iftype = type;
11721 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011722 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011723 goto done;
11724
11725 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011726 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011727 return -EOPNOTSUPP;
11728 }
11729 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011730 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011731 pAdapter->device_mode);
11732 return -EOPNOTSUPP;
11733 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011734done:
11735 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011736 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11737 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011738
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011739 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740
11741 EXIT();
11742 return 0;
11743}
11744
Rajeev Kumar98edb772016-01-19 12:42:19 -080011745/**
11746 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11747 * @wiphy: Pointer to the wiphy structure
11748 * @ndev: Pointer to the net device
11749 * @type: Interface type
11750 * @flags: Flags for change interface
11751 * @params: Pointer to change interface parameters
11752 *
11753 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011754 */
11755static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11756 struct net_device *ndev,
11757 enum nl80211_iftype type,
11758 u32 *flags,
11759 struct vif_params *params)
11760{
11761 int ret;
11762
11763 cds_ssr_protect(__func__);
11764 ret =
11765 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11766 cds_ssr_unprotect(__func__);
11767
11768 return ret;
11769}
11770
Frank Liud4b2fa02017-03-29 11:46:48 +080011771#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011772static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11773 int index, uint8_t match)
11774{
11775 int i;
11776 for (i = 0; i < index; i++) {
11777 if (arr[i] == match)
11778 return true;
11779 }
11780 return false;
11781}
11782#endif
11783
11784/**
11785 * __wlan_hdd_change_station() - change station
11786 * @wiphy: Pointer to the wiphy structure
11787 * @dev: Pointer to the net device.
11788 * @mac: bssid
11789 * @params: Pointer to station parameters
11790 *
11791 * Return: 0 for success, error number on failure.
11792 */
11793#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11794static int __wlan_hdd_change_station(struct wiphy *wiphy,
11795 struct net_device *dev,
11796 const uint8_t *mac,
11797 struct station_parameters *params)
11798#else
11799static int __wlan_hdd_change_station(struct wiphy *wiphy,
11800 struct net_device *dev,
11801 uint8_t *mac,
11802 struct station_parameters *params)
11803#endif
11804{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011805 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011806 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11807 hdd_context_t *pHddCtx;
11808 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011809 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011810#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011811 tCsrStaParams StaParams = { 0 };
11812 uint8_t isBufSta = 0;
11813 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011814 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011815#endif
11816 int ret;
11817
11818 ENTER();
11819
Anurag Chouhan6d760662016-02-20 16:05:43 +053011820 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011821 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011822 return -EINVAL;
11823 }
11824
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011825 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 TRACE_CODE_HDD_CHANGE_STATION,
11827 pAdapter->sessionId, params->listen_interval));
11828
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011829 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11830 hdd_err("invalid session id: %d", pAdapter->sessionId);
11831 return -EINVAL;
11832 }
11833
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11835 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011836 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011838
11839 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11840
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011841 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011842
Krunal Sonib4326f22016-03-10 13:05:51 -080011843 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11844 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011845 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11846 status =
11847 hdd_softap_change_sta_state(pAdapter,
11848 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011849 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011850
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011851 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011852 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011853 return -EINVAL;
11854 }
11855 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011856 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11857 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011858 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011859#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11860 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11861 dev, mac, params);
11862#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011863
11864 if (cds_is_sub_20_mhz_enabled()) {
11865 hdd_err("TDLS not allowed with sub 20 MHz");
11866 return -EINVAL;
11867 }
11868
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011869 StaParams.capability = params->capability;
11870 StaParams.uapsd_queues = params->uapsd_queues;
11871 StaParams.max_sp = params->max_sp;
11872
11873 /* Convert (first channel , number of channels) tuple to
11874 * the total list of channels. This goes with the assumption
11875 * that if the first channel is < 14, then the next channels
11876 * are an incremental of 1 else an incremental of 4 till the number
11877 * of channels.
11878 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011879 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011880 if (0 != params->supported_channels_len) {
11881 int i = 0, j = 0, k = 0, no_of_channels = 0;
11882 int num_unique_channels;
11883 int next;
11884 for (i = 0;
11885 i < params->supported_channels_len
11886 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11887 int wifi_chan_index;
11888 if (!wlan_hdd_is_duplicate_channel
11889 (StaParams.supported_channels, j,
11890 params->supported_channels[i])) {
11891 StaParams.
11892 supported_channels[j] =
11893 params->
11894 supported_channels[i];
11895 } else {
11896 continue;
11897 }
11898 wifi_chan_index =
11899 ((StaParams.supported_channels[j] <=
11900 HDD_CHANNEL_14) ? 1 : 4);
11901 no_of_channels =
11902 params->supported_channels[i + 1];
11903
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011904 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 -080011905 StaParams.
11906 supported_channels[j],
11907 wifi_chan_index,
11908 no_of_channels);
11909 for (k = 1; k <= no_of_channels &&
11910 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11911 k++) {
11912 next =
11913 StaParams.
11914 supported_channels[j] +
11915 wifi_chan_index;
11916 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11917 StaParams.
11918 supported_channels[j
11919 +
11920 1]
11921 = next;
11922 } else {
11923 continue;
11924 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011925 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011926 j + 1,
11927 StaParams.
11928 supported_channels[j +
11929 1]);
11930 j += 1;
11931 }
11932 }
11933 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011934 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011935 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011936 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011937 StaParams.
11938 supported_channels[i]);
11939 }
11940 if (MAX_CHANNEL < num_unique_channels)
11941 num_unique_channels = MAX_CHANNEL;
11942 StaParams.supported_channels_len =
11943 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011944 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011945 StaParams.supported_channels_len);
11946 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011947 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011948 params->supported_oper_classes,
11949 params->supported_oper_classes_len);
11950 StaParams.supported_oper_classes_len =
11951 params->supported_oper_classes_len;
11952
11953 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011954 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011955 params->ext_capab,
11956 sizeof(StaParams.extn_capability));
11957
11958 if (NULL != params->ht_capa) {
11959 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011960 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011961 sizeof(tSirHTCap));
11962 }
11963
11964 StaParams.supported_rates_len =
11965 params->supported_rates_len;
11966
11967 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11968 * The supported_rates array , for all the structures propogating till Add Sta
11969 * to the firmware has to be modified , if the supplicant (ieee80211) is
11970 * modified to send more rates.
11971 */
11972
11973 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11974 */
11975 if (StaParams.supported_rates_len >
11976 SIR_MAC_MAX_SUPP_RATES)
11977 StaParams.supported_rates_len =
11978 SIR_MAC_MAX_SUPP_RATES;
11979
11980 if (0 != StaParams.supported_rates_len) {
11981 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011982 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011983 params->supported_rates,
11984 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011985 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011986 StaParams.supported_rates_len);
11987 for (i = 0; i < StaParams.supported_rates_len;
11988 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011989 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011990 StaParams.supported_rates[i]);
11991 }
11992
11993 if (NULL != params->vht_capa) {
11994 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011995 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011996 params->vht_capa,
11997 sizeof(tSirVHTCap));
11998 }
11999
12000 if (0 != params->ext_capab_len) {
12001 /*Define A Macro : TODO Sunil */
12002 if ((1 << 4) & StaParams.extn_capability[3]) {
12003 isBufSta = 1;
12004 }
12005 /* TDLS Channel Switching Support */
12006 if ((1 << 6) & StaParams.extn_capability[3]) {
12007 isOffChannelSupported = 1;
12008 }
12009 }
12010
Nitesh Shah99934ac2016-09-05 15:54:08 +053012011 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053012012 (params->ht_capa || params->vht_capa ||
12013 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053012014 is_qos_wmm_sta = true;
12015
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012016 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053012017 " is_qos_wmm_sta= %d HTcapPresent = %d",
12018 __func__, is_qos_wmm_sta,
12019 StaParams.htcap_present);
12020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012021 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053012022 &StaParams,
12023 isBufSta,
12024 isOffChannelSupported,
12025 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012026 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012027 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012028 return -EINVAL;
12029 }
12030
12031 status =
12032 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
12033 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012034 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012035 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012036 return -EINVAL;
12037 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012038#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080012039 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012040 }
12041 EXIT();
12042 return ret;
12043}
12044
12045/**
12046 * wlan_hdd_change_station() - cfg80211 change station handler function
12047 * @wiphy: Pointer to the wiphy structure
12048 * @dev: Pointer to the net device.
12049 * @mac: bssid
12050 * @params: Pointer to station parameters
12051 *
12052 * This is the cfg80211 change station handler function which invokes
12053 * the internal function @__wlan_hdd_change_station with
12054 * SSR protection.
12055 *
12056 * Return: 0 for success, error number on failure.
12057 */
12058#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
12059static int wlan_hdd_change_station(struct wiphy *wiphy,
12060 struct net_device *dev,
12061 const u8 *mac,
12062 struct station_parameters *params)
12063#else
12064static int wlan_hdd_change_station(struct wiphy *wiphy,
12065 struct net_device *dev,
12066 u8 *mac,
12067 struct station_parameters *params)
12068#endif
12069{
12070 int ret;
12071
12072 cds_ssr_protect(__func__);
12073 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
12074 cds_ssr_unprotect(__func__);
12075
12076 return ret;
12077}
12078
12079/*
12080 * FUNCTION: __wlan_hdd_cfg80211_add_key
12081 * This function is used to initialize the key information
12082 */
12083static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12084 struct net_device *ndev,
12085 u8 key_index, bool pairwise,
12086 const u8 *mac_addr,
12087 struct key_params *params)
12088{
12089 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12090 tCsrRoamSetKey setKey;
12091 int status;
12092 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012093 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012094 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012095 hdd_context_t *pHddCtx;
12096 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12097
12098 ENTER();
12099
Anurag Chouhan6d760662016-02-20 16:05:43 +053012100 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012101 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012102 return -EINVAL;
12103 }
12104
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012105 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012106 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012107 return -EINVAL;
12108 }
12109
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012110 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012111 TRACE_CODE_HDD_CFG80211_ADD_KEY,
12112 pAdapter->sessionId, params->key_len));
12113 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12114 status = wlan_hdd_validate_context(pHddCtx);
12115
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012116 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012118
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012119 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012120 hdd_device_mode_to_string(pAdapter->device_mode),
12121 pAdapter->device_mode);
12122
12123 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012124 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012125
12126 return -EINVAL;
12127 }
12128
12129 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012130 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012131
12132 return -EINVAL;
12133 }
12134
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012135 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012136
12137 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012138 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012139 setKey.keyId = key_index;
12140 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012141 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012142
12143 switch (params->cipher) {
12144 case WLAN_CIPHER_SUITE_WEP40:
12145 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12146 break;
12147
12148 case WLAN_CIPHER_SUITE_WEP104:
12149 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
12150 break;
12151
12152 case WLAN_CIPHER_SUITE_TKIP:
12153 {
12154 u8 *pKey = &setKey.Key[0];
12155 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
12156
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012157 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012158
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012159 /* Supplicant sends the 32bytes key in this order
12160 *
12161 * |--------------|----------|----------|
12162 * | Tk1 |TX-MIC | RX Mic |
12163 * |--------------|----------|----------|
12164 * <---16bytes---><--8bytes--><--8bytes-->
12165 *
12166 * Sme expects the 32 bytes key to be in the below order
12167 *
12168 * |--------------|----------|----------|
12169 * | Tk1 |RX-MIC | TX Mic |
12170 * |--------------|----------|----------|
12171 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012172 */
12173 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012174 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012175
12176 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012177 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012178
12179 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012180 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012181
12182 break;
12183 }
12184
12185 case WLAN_CIPHER_SUITE_CCMP:
12186 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
12187 break;
12188
12189#ifdef FEATURE_WLAN_WAPI
12190 case WLAN_CIPHER_SUITE_SMS4:
12191 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012192 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012193 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
12194 mac_addr, params->key,
12195 params->key_len);
12196 return 0;
12197 }
12198#endif
12199
12200#ifdef FEATURE_WLAN_ESE
12201 case WLAN_CIPHER_SUITE_KRK:
12202 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
12203 break;
12204#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12205 case WLAN_CIPHER_SUITE_BTK:
12206 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
12207 break;
12208#endif
12209#endif
12210
12211#ifdef WLAN_FEATURE_11W
12212 case WLAN_CIPHER_SUITE_AES_CMAC:
12213 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
12214 break;
12215#endif
12216
12217 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012218 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012219 return -EOPNOTSUPP;
12220 }
12221
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012222 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012223
12224 if (!pairwise) {
12225 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012226 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012227 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012228 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012229 } else {
12230 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012231 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012232 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012233 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012234 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012235 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012236 /* if a key is already installed, block all subsequent ones */
12237 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012238 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012239 return 0;
12240 }
12241
12242 setKey.keyDirection = eSIR_TX_RX;
12243 /*Set the group key */
12244 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12245 pAdapter->sessionId, &setKey, &roamId);
12246
12247 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012248 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249 return -EINVAL;
12250 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012251 /* Save the keys here and call sme_roam_set_key for setting
12252 * the PTK after peer joins the IBSS network
12253 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012254 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012255 &setKey, sizeof(tCsrRoamSetKey));
12256
12257 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
12258 return status;
12259 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012260 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
12261 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012262 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
12263 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070012264 status = wlansap_set_key_sta(
12265 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012266 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012267 hdd_err("wlansap_set_key_sta failed status: %d",
12268 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012269 }
12270 }
12271
12272 /* Save the key in ap ctx for use on START_BASS and restart */
12273 if (pairwise ||
12274 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
12275 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012276 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012277 sizeof(tCsrRoamSetKey));
12278 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012279 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012280 sizeof(tCsrRoamSetKey));
12281
Krunal Sonib4326f22016-03-10 13:05:51 -080012282 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
12283 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012284 hdd_wext_state_t *pWextState =
12285 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12286 hdd_station_ctx_t *pHddStaCtx =
12287 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12288
12289 if (!pairwise) {
12290 /* set group key */
12291 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012292 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012293 __func__, __LINE__);
12294 hdd_perform_roam_set_key_complete(pAdapter);
12295 }
12296 }
12297
12298 pWextState->roamProfile.Keys.KeyLength[key_index] =
12299 (u8) params->key_len;
12300
12301 pWextState->roamProfile.Keys.defaultIndex = key_index;
12302
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012303 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012304 KeyMaterial[key_index][0], params->key,
12305 params->key_len);
12306
12307 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
12308
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012309 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012310 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12311 setKey.keyDirection);
12312
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012313 /* The supplicant may attempt to set the PTK once
12314 * pre-authentication is done. Save the key in the
12315 * UMAC and include it in the ADD BSS request
12316 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012317 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012318 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012319 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012320 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012321 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012322 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012323 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324 return -EINVAL;
12325 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012326
12327 /* issue set key request to SME */
12328 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12329 pAdapter->sessionId, &setKey, &roamId);
12330
12331 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012332 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 pHddStaCtx->roam_info.roamingState =
12334 HDD_ROAM_STATE_NONE;
12335 return -EINVAL;
12336 }
12337
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012338 /* in case of IBSS as there was no information
12339 * available about WEP keys during IBSS join, group
12340 * key intialized with NULL key, so re-initialize
12341 * group key with correct value
12342 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343 if ((eCSR_BSS_TYPE_START_IBSS ==
12344 pWextState->roamProfile.BSSType)
12345 &&
12346 !((IW_AUTH_KEY_MGMT_802_1X ==
12347 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
12348 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
12349 pHddStaCtx->conn_info.authType)
12350 )
12351 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
12352 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
12353 )
12354 ) {
12355 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012356 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012357
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012358 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012359 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12360 setKey.keyDirection);
12361
12362 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12363 pAdapter->sessionId, &setKey,
12364 &roamId);
12365
12366 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012367 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012368 pHddStaCtx->roam_info.roamingState =
12369 HDD_ROAM_STATE_NONE;
12370 return -EINVAL;
12371 }
12372 }
12373 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012374 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012375 return 0;
12376}
12377
12378static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12379 struct net_device *ndev,
12380 u8 key_index, bool pairwise,
12381 const u8 *mac_addr,
12382 struct key_params *params)
12383{
12384 int ret;
12385 cds_ssr_protect(__func__);
12386 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
12387 mac_addr, params);
12388 cds_ssr_unprotect(__func__);
12389
12390 return ret;
12391}
12392
12393/*
12394 * FUNCTION: __wlan_hdd_cfg80211_get_key
12395 * This function is used to get the key information
12396 */
12397static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12398 struct net_device *ndev,
12399 u8 key_index, bool pairwise,
12400 const u8 *mac_addr, void *cookie,
12401 void (*callback)(void *cookie,
12402 struct key_params *)
12403 )
12404{
12405 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12406 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12407 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
12408 struct key_params params;
12409
12410 ENTER();
12411
Anurag Chouhan6d760662016-02-20 16:05:43 +053012412 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012413 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012414 return -EINVAL;
12415 }
12416
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012417 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012418 hdd_device_mode_to_string(pAdapter->device_mode),
12419 pAdapter->device_mode);
12420
12421 memset(&params, 0, sizeof(params));
12422
12423 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012424 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012425 return -EINVAL;
12426 }
12427
12428 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12429 case eCSR_ENCRYPT_TYPE_NONE:
12430 params.cipher = IW_AUTH_CIPHER_NONE;
12431 break;
12432
12433 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12434 case eCSR_ENCRYPT_TYPE_WEP40:
12435 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12436 break;
12437
12438 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12439 case eCSR_ENCRYPT_TYPE_WEP104:
12440 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12441 break;
12442
12443 case eCSR_ENCRYPT_TYPE_TKIP:
12444 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12445 break;
12446
12447 case eCSR_ENCRYPT_TYPE_AES:
12448 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12449 break;
12450
12451 default:
12452 params.cipher = IW_AUTH_CIPHER_NONE;
12453 break;
12454 }
12455
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012456 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012457 TRACE_CODE_HDD_CFG80211_GET_KEY,
12458 pAdapter->sessionId, params.cipher));
12459
12460 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12461 params.seq_len = 0;
12462 params.seq = NULL;
12463 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12464 callback(cookie, &params);
12465
12466 EXIT();
12467 return 0;
12468}
12469
12470static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12471 struct net_device *ndev,
12472 u8 key_index, bool pairwise,
12473 const u8 *mac_addr, void *cookie,
12474 void (*callback)(void *cookie,
12475 struct key_params *)
12476 )
12477{
12478 int ret;
12479
12480 cds_ssr_protect(__func__);
12481 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12482 mac_addr, cookie, callback);
12483 cds_ssr_unprotect(__func__);
12484
12485 return ret;
12486}
12487
12488/**
12489 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12490 * @wiphy: wiphy interface context
12491 * @ndev: pointer to net device
12492 * @key_index: Key index used in 802.11 frames
12493 * @unicast: true if it is unicast key
12494 * @multicast: true if it is multicast key
12495 *
12496 * This function is required for cfg80211_ops API.
12497 * It is used to delete the key information
12498 * Underlying hardware implementation does not have API to delete the
12499 * encryption key. It is automatically deleted when the peer is
12500 * removed. Hence this function currently does nothing.
12501 * Future implementation may interprete delete key operation to
12502 * replacing the key with a random junk value, effectively making it
12503 * useless.
12504 *
12505 * Return: status code, always 0.
12506 */
12507
12508static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12509 struct net_device *ndev,
12510 u8 key_index,
12511 bool pairwise, const u8 *mac_addr)
12512{
12513 EXIT();
12514 return 0;
12515}
12516
12517/**
12518 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12519 * @wiphy: Pointer to wiphy structure.
12520 * @dev: Pointer to net_device structure.
12521 * @key_index: key index
12522 * @pairwise: pairwise
12523 * @mac_addr: mac address
12524 *
12525 * This is the cfg80211 delete key handler function which invokes
12526 * the internal function @__wlan_hdd_cfg80211_del_key with
12527 * SSR protection.
12528 *
12529 * Return: 0 for success, error number on failure.
12530 */
12531static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12532 struct net_device *dev,
12533 u8 key_index,
12534 bool pairwise, const u8 *mac_addr)
12535{
12536 int ret;
12537
12538 cds_ssr_protect(__func__);
12539 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12540 pairwise, mac_addr);
12541 cds_ssr_unprotect(__func__);
12542
12543 return ret;
12544}
12545
12546/*
12547 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12548 * This function is used to set the default tx key index
12549 */
12550static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12551 struct net_device *ndev,
12552 u8 key_index,
12553 bool unicast, bool multicast)
12554{
12555 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12556 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12557 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12558 hdd_context_t *pHddCtx;
12559 int status;
12560
12561 ENTER();
12562
Anurag Chouhan6d760662016-02-20 16:05:43 +053012563 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012564 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012565 return -EINVAL;
12566 }
12567
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012568 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012569 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012570 return -EINVAL;
12571 }
12572
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012573 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12575 pAdapter->sessionId, key_index));
12576
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012577 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012578 hdd_device_mode_to_string(pAdapter->device_mode),
12579 pAdapter->device_mode, key_index);
12580
12581 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012582 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012583 return -EINVAL;
12584 }
12585
12586 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12587 status = wlan_hdd_validate_context(pHddCtx);
12588
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012589 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012590 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012591
Krunal Sonib4326f22016-03-10 13:05:51 -080012592 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12593 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012594 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12595 pHddStaCtx->conn_info.ucEncryptionType) &&
12596 (eCSR_ENCRYPT_TYPE_AES !=
12597 pHddStaCtx->conn_info.ucEncryptionType)) {
12598 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012599 * then update the default key index
12600 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012601
12602 tCsrRoamSetKey setKey;
12603 uint32_t roamId = 0xFF;
12604 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12605
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012606 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607
12608 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012609 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012610 setKey.keyId = key_index;
12611 setKey.keyLength = Keys->KeyLength[key_index];
12612
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012613 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012614 &Keys->KeyMaterial[key_index][0],
12615 Keys->KeyLength[key_index]);
12616
12617 setKey.keyDirection = eSIR_TX_RX;
12618
Anurag Chouhanc5548422016-02-24 18:33:27 +053012619 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012620 &pHddStaCtx->conn_info.bssId);
12621
12622 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12623 pWextState->roamProfile.EncryptionType.
12624 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012625 /* In the case of dynamic wep
12626 * supplicant hardcodes DWEP type to
12627 * eCSR_ENCRYPT_TYPE_WEP104 even
12628 * though ap is configured for WEP-40
12629 * encryption. In this canse the key
12630 * length is 5 but the encryption type
12631 * is 104 hence checking the key
12632 * lenght(5) and encryption type(104)
12633 * and switching encryption type to 40
12634 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012635 pWextState->roamProfile.EncryptionType.
12636 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12637 pWextState->roamProfile.mcEncryptionType.
12638 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12639 }
12640
12641 setKey.encType =
12642 pWextState->roamProfile.EncryptionType.
12643 encryptionType[0];
12644
12645 /* Issue set key request */
12646 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12647 pAdapter->sessionId, &setKey,
12648 &roamId);
12649
12650 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012651 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012652 status);
12653 return -EINVAL;
12654 }
12655 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012656 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012657 /* In SoftAp mode setting key direction for default mode */
12658 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12659 pWextState->roamProfile.EncryptionType.encryptionType[0])
12660 && (eCSR_ENCRYPT_TYPE_AES !=
12661 pWextState->roamProfile.EncryptionType.
12662 encryptionType[0])) {
12663 /* Saving key direction for default key index to TX default */
12664 hdd_ap_ctx_t *pAPCtx =
12665 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12666 pAPCtx->wepKey[key_index].keyDirection =
12667 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012668 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012669 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012670 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671 }
12672 }
12673
12674 EXIT();
12675 return status;
12676}
12677
12678static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12679 struct net_device *ndev,
12680 u8 key_index,
12681 bool unicast, bool multicast)
12682{
12683 int ret;
12684 cds_ssr_protect(__func__);
12685 ret =
12686 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12687 multicast);
12688 cds_ssr_unprotect(__func__);
12689
12690 return ret;
12691}
12692
Abhishek Singhc9941602016-08-09 16:06:22 +053012693/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012694 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12695 * interface that BSS might have been lost.
12696 * @pAdapter: adaptor
12697 * @bssid: bssid which might have been lost
12698 *
12699 * Return: bss which is unlinked from kernel cache
12700 */
12701struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12702 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012703{
12704 struct net_device *dev = pAdapter->dev;
12705 struct wireless_dev *wdev = dev->ieee80211_ptr;
12706 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012707 struct cfg80211_bss *bss = NULL;
12708
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012709 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012710 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012711 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012712 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012713 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012714 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012715 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012716 cfg80211_unlink_bss(wiphy, bss);
12717 }
12718 return bss;
12719}
12720
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012721#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12722 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12723static struct cfg80211_bss *
12724wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12725 struct ieee80211_channel *chan,
12726 struct ieee80211_mgmt *mgmt,
12727 size_t frame_len,
12728 int rssi, gfp_t gfp,
12729 uint64_t boottime_ns)
12730{
12731 struct cfg80211_bss *bss_status = NULL;
12732 struct cfg80211_inform_bss data = {0};
12733
12734 data.chan = chan;
12735 data.boottime_ns = boottime_ns;
12736 data.signal = rssi;
12737 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12738 frame_len, gfp);
12739 return bss_status;
12740}
12741#else
12742static struct cfg80211_bss *
12743wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12744 struct ieee80211_channel *chan,
12745 struct ieee80211_mgmt *mgmt,
12746 size_t frame_len,
12747 int rssi, gfp_t gfp,
12748 uint64_t boottime_ns)
12749{
12750 struct cfg80211_bss *bss_status = NULL;
12751
12752 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12753 rssi, gfp);
12754 return bss_status;
12755}
12756#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012757
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012758/**
12759 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12760 * @pAdapter: Pointer to adapter
12761 * @bss_desc: Pointer to bss descriptor
12762 *
12763 * This function is used to inform the BSS details to nl80211 interface.
12764 *
12765 * Return: struct cfg80211_bss pointer
12766 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012767struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12768 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012769{
12770 /*
12771 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12772 * already exists in bss data base of cfg80211 for that particular BSS
12773 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12774 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12775 * As of now there is no possibility to get the mgmt(probe response)
12776 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12777 * and passing to cfg80211_inform_bss_frame.
12778 */
12779 struct net_device *dev = pAdapter->dev;
12780 struct wireless_dev *wdev = dev->ieee80211_ptr;
12781 struct wiphy *wiphy = wdev->wiphy;
12782 int chan_no = bss_desc->channelId;
12783#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12784 qcom_ie_age *qie_age = NULL;
12785 int ie_length =
12786 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12787#else
12788 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12789#endif
12790 const char *ie =
12791 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12792 unsigned int freq;
12793 struct ieee80211_channel *chan;
12794 struct ieee80211_mgmt *mgmt = NULL;
12795 struct cfg80211_bss *bss_status = NULL;
12796 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12797 int rssi = 0;
12798 hdd_context_t *pHddCtx;
12799 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012800 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012801 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012802
12803 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12804 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012805 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012806 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012807
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012808 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012809 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012810 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012811 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012812 return NULL;
12813 }
12814
12815 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12816
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012817 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012818 * Instead it wants a monotonic increasing value
12819 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012820 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012821 mgmt->u.probe_resp.timestamp =
12822 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012823
12824 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12825 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12826
12827#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12828 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12829 /* Assuming this is the last IE, copy at the end */
12830 ie_length -= sizeof(qcom_ie_age);
12831 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12832 qie_age->element_id = QCOM_VENDOR_IE_ID;
12833 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12834 qie_age->oui_1 = QCOM_OUI1;
12835 qie_age->oui_2 = QCOM_OUI2;
12836 qie_age->oui_3 = QCOM_OUI3;
12837 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012838 /*
12839 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12840 * all bss related timestamp is in units of ms. Due to this when scan
12841 * results are sent to lowi the scan age is high.To address this,
12842 * send age in units of 1/10 ms.
12843 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012844 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012845 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012846 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012847 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12848 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012849 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12850 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012851#endif
12852
12853 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12854 if (bss_desc->fProbeRsp) {
12855 mgmt->frame_control |=
12856 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12857 } else {
12858 mgmt->frame_control |=
12859 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12860 }
12861
12862 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012863 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012864 freq =
12865 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012866 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012867 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012868 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012869 freq =
12870 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012871 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012872 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012873 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012874 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012875 return NULL;
12876 }
12877
12878 chan = __ieee80211_get_channel(wiphy, freq);
12879 /* When the band is changed on the fly using the GUI, three things are done
12880 * 1. scan abort
12881 * 2. flush scan results from cache
12882 * 3. update the band with the new band user specified (refer to the
12883 * hdd_set_band_helper function) as part of the scan abort, message will be
12884 * queued to PE and we proceed with flushing and changinh the band.
12885 * PE will stop the scanning further and report back the results what ever
12886 * it had till now by calling the call back function.
12887 * if the time between update band and scandone call back is sufficient
12888 * enough the band change reflects in SME, SME validates the channels
12889 * and discards the channels correponding to previous band and calls back
12890 * with zero bss results. but if the time between band update and scan done
12891 * callback is very small then band change will not reflect in SME and SME
12892 * reports to HDD all the channels correponding to previous band.this is due
12893 * to race condition.but those channels are invalid to the new band and so
12894 * this function __ieee80211_get_channel will return NULL.Each time we
12895 * report scan result with this pointer null warning kernel trace is printed.
12896 * if the scan results contain large number of APs continuosly kernel
12897 * warning trace is printed and it will lead to apps watch dog bark.
12898 * So drop the bss and continue to next bss.
12899 */
12900 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012901 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12902 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012903 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012904 return NULL;
12905 }
12906
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012907 /* Based on .ini configuration, raw rssi can be reported for bss.
12908 * Raw rssi is typically used for estimating power.
12909 */
12910
12911 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12912 bss_desc->rssi;
12913
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012914 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012915 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012916
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012917 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012918 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012919 (int)(rssi / 100),
12920 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012921
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012922 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12923 frame_len, rssi,
12924 GFP_KERNEL,
12925 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012926 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012927 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012928 return bss_status;
12929}
12930
12931/**
12932 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12933 * @pAdapter: Pointer to adapter
12934 * @pRoamInfo: Pointer to roam info
12935 *
12936 * This function is used to update the BSS data base of CFG8011
12937 *
12938 * Return: struct cfg80211_bss pointer
12939 */
12940struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12941 tCsrRoamInfo *pRoamInfo)
12942{
12943 tCsrRoamConnectedProfile roamProfile;
12944 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12945 struct cfg80211_bss *bss = NULL;
12946
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012947 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12948 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12949
12950 if (NULL != roamProfile.pBssDesc) {
12951 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12952 roamProfile.pBssDesc);
12953
12954 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012955 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012956
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012957 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012958 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012959 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012960 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961 return bss;
12962}
12963/**
12964 * wlan_hdd_cfg80211_update_bss() - update bss
12965 * @wiphy: Pointer to wiphy
12966 * @pAdapter: Pointer to adapter
12967 * @scan_time: scan request timestamp
12968 *
12969 * Return: zero if success, non-zero otherwise
12970 */
12971int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12972 hdd_adapter_t *pAdapter,
12973 uint32_t scan_time)
12974{
12975 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12976 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012977 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012978 tScanResultHandle pResult;
12979 struct cfg80211_bss *bss_status = NULL;
12980 hdd_context_t *pHddCtx;
12981 int ret;
12982
12983 ENTER();
12984
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012985 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12986 hdd_err("invalid session id: %d", pAdapter->sessionId);
12987 return -EINVAL;
12988 }
12989
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012990 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012991 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12992 NO_SESSION, pAdapter->sessionId));
12993
12994 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12995 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012996 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012997 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998
12999 /* start getting scan results and populate cgf80211 BSS database */
13000 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
13001
13002 /* no scan results */
13003 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013004 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053013005 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013006 }
13007
13008 pScanResult = sme_scan_result_get_first(hHal, pResult);
13009
13010 while (pScanResult) {
13011 /*
13012 * - cfg80211_inform_bss() is not updating ie field of bss
13013 * entry if entry already exists in bss data base of cfg80211
13014 * for that particular BSS ID. Using cfg80211_inform_bss_frame
13015 * to update thebss entry instead of cfg80211_inform_bss,
13016 * But this call expects mgmt packet as input. As of now
13017 * there is no possibility to get the mgmt(probe response)
13018 * frame from PE, converting bss_desc to
13019 * ieee80211_mgmt(probe response) and passing to c
13020 * fg80211_inform_bss_frame.
13021 * - Update BSS only if beacon timestamp is later than
13022 * scan request timestamp.
13023 */
13024 if ((scan_time == 0) ||
13025 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053013026 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013027 bss_status =
13028 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
13029 &pScanResult->BssDescriptor);
13030
13031 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013032 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013033 } else {
13034 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013035 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013036 bss_status);
13037 }
13038 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013039 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
13041 }
13042 pScanResult = sme_scan_result_get_next(hHal, pResult);
13043 }
13044
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070013045 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013046 /*
13047 * For SAP mode, scan is invoked by hostapd during SAP start
13048 * if hostapd is restarted, we need to flush previous scan
13049 * result so that it will reflect environment change
13050 */
Krunal Sonib4326f22016-03-10 13:05:51 -080013051 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013052#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
13053 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
13054#endif
13055 )
13056 sme_scan_flush_result(hHal);
13057
13058 EXIT();
13059 return 0;
13060}
13061
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013062/**
13063 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
13064 * @pAdapter: Pointer to adapter
13065 * @pRoamInfo: Pointer to roam info
13066 * @index: Index
13067 * @preauth: Preauth flag
13068 *
13069 * This function is used to notify the supplicant of a new PMKSA candidate.
13070 *
13071 * Return: 0 for success, non-zero for failure
13072 */
13073int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
13074 tCsrRoamInfo *pRoamInfo,
13075 int index, bool preauth)
13076{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013077 struct net_device *dev = pAdapter->dev;
13078 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
13079
13080 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013081 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013082
13083 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013084 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013085 return -EINVAL;
13086 }
13087
13088 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013089 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
13091 cfg80211_pmksa_candidate_notify(dev, index,
13092 pRoamInfo->bssid.bytes,
13093 preauth, GFP_KERNEL);
13094 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013095 return 0;
13096}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013097
13098#ifdef FEATURE_WLAN_LFR_METRICS
13099/**
13100 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
13101 * @pAdapter: Pointer to adapter
13102 * @pRoamInfo: Pointer to roam info
13103 *
13104 * 802.11r/LFR metrics reporting function to report preauth initiation
13105 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013106 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013107 */
13108#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013109QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013110 tCsrRoamInfo *pRoamInfo)
13111{
13112 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13113 union iwreq_data wrqu;
13114
13115 ENTER();
13116
13117 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013118 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013119 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013120 }
13121
13122 /* create the event */
13123 memset(&wrqu, 0, sizeof(wrqu));
13124 memset(metrics_notification, 0, sizeof(metrics_notification));
13125
13126 wrqu.data.pointer = metrics_notification;
13127 wrqu.data.length = scnprintf(metrics_notification,
13128 sizeof(metrics_notification),
13129 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013130 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013131
13132 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13133 metrics_notification);
13134
13135 EXIT();
13136
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013137 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013138}
13139
13140/**
13141 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13142 * @pAdapter: Pointer to adapter
13143 * @pRoamInfo: Pointer to roam info
13144 * @preauth_status: Preauth status
13145 *
13146 * 802.11r/LFR metrics reporting function to report handover initiation
13147 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013148 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013149 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013150QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013151wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
13152 tCsrRoamInfo *pRoamInfo,
13153 bool preauth_status)
13154{
13155 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13156 union iwreq_data wrqu;
13157
13158 ENTER();
13159
13160 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013161 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013162 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013163 }
13164
13165 /* create the event */
13166 memset(&wrqu, 0, sizeof(wrqu));
13167 memset(metrics_notification, 0, sizeof(metrics_notification));
13168
13169 scnprintf(metrics_notification, sizeof(metrics_notification),
13170 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013171 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013172
13173 if (1 == preauth_status)
13174 strlcat(metrics_notification, " true",
13175 sizeof(metrics_notification));
13176 else
13177 strlcat(metrics_notification, " false",
13178 sizeof(metrics_notification));
13179
13180 wrqu.data.pointer = metrics_notification;
13181 wrqu.data.length = strlen(metrics_notification);
13182
13183 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13184 metrics_notification);
13185
13186 EXIT();
13187
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013188 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013189}
13190
13191/**
13192 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13193 * @pAdapter: Pointer to adapter
13194 * @pRoamInfo: Pointer to roam info
13195 *
13196 * 802.11r/LFR metrics reporting function to report handover initiation
13197 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013198 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013199 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013200QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013201 tCsrRoamInfo *pRoamInfo)
13202{
13203 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13204 union iwreq_data wrqu;
13205
13206 ENTER();
13207
13208 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013209 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013210 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013211 }
13212
13213 /* create the event */
13214 memset(&wrqu, 0, sizeof(wrqu));
13215 memset(metrics_notification, 0, sizeof(metrics_notification));
13216
13217 wrqu.data.pointer = metrics_notification;
13218 wrqu.data.length = scnprintf(metrics_notification,
13219 sizeof(metrics_notification),
13220 "QCOM: LFR_PREAUTH_HANDOVER "
13221 MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013222 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013223
13224 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13225 metrics_notification);
13226
13227 EXIT();
13228
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013229 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013230}
13231#endif
13232
13233/**
13234 * hdd_select_cbmode() - select channel bonding mode
13235 * @pAdapter: Pointer to adapter
13236 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013237 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013238 *
13239 * Return: none
13240 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013241void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080013242 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013243{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013244 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013245 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013246 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013247 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013248
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013249 /*
13250 * CDS api expects secondary channel for calculating
13251 * the channel params
13252 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013253 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013254 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013255 if (operationChannel >= 1 && operationChannel <= 5)
13256 sec_ch = operationChannel + 4;
13257 else if (operationChannel >= 6 && operationChannel <= 13)
13258 sec_ch = operationChannel - 4;
13259 }
13260
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013261 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013262 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
13263 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013264
13265 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070013266 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013267 uint8_t iniDot11Mode =
13268 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
13269
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013270 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013271 switch (iniDot11Mode) {
13272 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080013273 case eHDD_DOT11_MODE_11ax:
13274 case eHDD_DOT11_MODE_11ax_ONLY:
13275 if (sme_is_feature_supported_by_fw(DOT11AX))
13276 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
13277 else if (sme_is_feature_supported_by_fw(DOT11AC))
13278 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13279 else
13280 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13281 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013282 case eHDD_DOT11_MODE_11ac:
13283 case eHDD_DOT11_MODE_11ac_ONLY:
13284 if (sme_is_feature_supported_by_fw(DOT11AC))
13285 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13286 else
13287 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13288 break;
13289 case eHDD_DOT11_MODE_11n:
13290 case eHDD_DOT11_MODE_11n_ONLY:
13291 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13292 break;
13293 default:
13294 hdd_dot11_mode = iniDot11Mode;
13295 break;
13296 }
13297 ch_info->channel_width = ch_params->ch_width;
13298 ch_info->phy_mode =
13299 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013300 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013301 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013302 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013303 ch_info->channel_width, ch_info->phy_mode,
13304 ch_info->channel);
13305 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013306}
13307
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013308/**
13309 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
13310 * @adapter: STA adapter
13311 * @roam_profile: STA roam profile
13312 *
13313 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
13314 *
13315 * Return: false if sta-sap conc is not allowed, else return true
13316 */
13317static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
13318 tCsrRoamProfile *roam_profile)
13319{
13320 hdd_context_t *hdd_ctx;
13321 hdd_adapter_t *ap_adapter;
13322 hdd_ap_ctx_t *hdd_ap_ctx;
13323 hdd_hostapd_state_t *hostapd_state;
13324 uint8_t channel = 0;
13325 QDF_STATUS status;
13326
13327 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13328 if (!hdd_ctx) {
13329 hdd_err("HDD context is NULL");
13330 return true;
13331 }
13332
13333 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
13334 /* probably no sap running, no handling required */
13335 if (ap_adapter == NULL)
13336 return true;
13337
13338 /*
13339 * sap is not in started state, so it is fine to go ahead with sta.
13340 * if sap is currently doing CAC then don't allow sta to go further.
13341 */
13342 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
13343 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
13344 return true;
13345
13346 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
13347 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
13348 return false;
13349 }
13350
13351 /*
13352 * log and return error, if we allow STA to go through, we don't
13353 * know what is going to happen better stop sta connection
13354 */
13355 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
13356 if (NULL == hdd_ap_ctx) {
13357 hdd_err("AP context not found");
13358 return false;
13359 }
13360
13361 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013362 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
13363 hdd_ap_ctx->operatingChannel)) {
13364 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013365 return true;
13366 }
13367 /*
13368 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053013369 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013370 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013371 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013372 roam_profile, &channel);
13373
Nitesh Shah59774522016-09-16 15:14:21 +053013374 /*
13375 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
13376 * channels for roaming case.
13377 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013378 if (WLAN_REG_IS_24GHZ_CH(channel)) {
13379 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053013380 return true;
13381 }
13382
13383 /*
13384 * If channel is 0 or DFS then better to call pcl and find out the
13385 * best channel. If channel is non-dfs 5 GHz then better move SAP
13386 * to STA's channel to make scc, so we have room for 3port MCC
13387 * scenario.
13388 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013389 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013390 channel = policy_mgr_get_nondfs_preferred_channel(
13391 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013392
13393 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
13394 qdf_event_reset(&hostapd_state->qdf_event);
13395 status = wlansap_set_channel_change_with_csa(
13396 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
13397 hdd_ap_ctx->sapConfig.ch_width_orig);
13398
13399 if (QDF_STATUS_SUCCESS != status) {
13400 hdd_err("Set channel with CSA IE failed, can't allow STA");
13401 return false;
13402 }
13403
13404 /*
13405 * wait here for SAP to finish the channel switch. When channel
13406 * switch happens, SAP sends few beacons with CSA_IE. After
13407 * successfully Transmission of those beacons, it will move its
13408 * state from started to disconnected and move to new channel.
13409 * once it moves to new channel, sap again moves its state
13410 * machine from disconnected to started and set this event.
13411 * wait for 10 secs to finish this.
13412 */
13413 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
13414 if (!QDF_IS_STATUS_SUCCESS(status)) {
13415 hdd_err("wait for qdf_event failed, STA not allowed!!");
13416 return false;
13417 }
13418
13419 return true;
13420}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013421
Abhishek Singhcfb44482017-03-10 12:42:37 +053013422#ifdef WLAN_FEATURE_11W
13423/**
13424 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13425 * @roam_profile: pointer to roam profile
13426 *
13427 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13428 * or pmf=2 is an explicit configuration in the supplicant
13429 * configuration, drop the connection request.
13430 *
13431 * Return: 0 if check result is valid, otherwise return error code
13432 */
13433static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13434{
13435 if (roam_profile->MFPEnabled &&
13436 !(roam_profile->MFPRequired ||
13437 roam_profile->MFPCapable)) {
13438 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13439 roam_profile->MFPEnabled,
13440 roam_profile->MFPRequired,
13441 roam_profile->MFPCapable);
13442 return -EINVAL;
13443 }
13444 return 0;
13445}
13446#else
13447static inline
13448int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13449{
13450 return 0;
13451}
13452#endif
13453
Krunal Soni31949422016-07-29 17:17:53 -070013454/**
13455 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013456 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013457 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013458 * @ssid_len: Length of ssid
13459 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013460 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013461 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013462 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013463 *
13464 * This function is used to start the association process
13465 *
13466 * Return: 0 for success, non-zero for failure
13467 */
Krunal Soni31949422016-07-29 17:17:53 -070013468static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013469 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013470 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013471 u8 operatingChannel,
13472 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013473{
13474 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013475 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013476 hdd_wext_state_t *pWextState;
13477 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013478 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013479 uint32_t roamId;
13480 tCsrRoamProfile *pRoamProfile;
13481 eCsrAuthType RSNAuthType;
13482 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013483 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013484
13485 ENTER();
13486
13487 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13488 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013489 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013490
13491 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013492 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013493 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013494
13495 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013496 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013497 status = -EINVAL;
13498 goto ret_status;
13499 }
13500
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013501 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013502 hdd_err("Connection refused: conn in progress");
13503 status = -EINVAL;
13504 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013505 }
13506
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013507 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013508 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13509
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013510 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013511 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13512 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513
13514 if (pRoamProfile) {
13515 hdd_station_ctx_t *pHddStaCtx;
13516 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13517
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013518 /* Restart the opportunistic timer
13519 *
13520 * If hw_mode_change_in_progress is true, then wait
13521 * till firmware sends the callback for hw_mode change.
13522 *
13523 * Else set connect_in_progress as true and proceed.
13524 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013525 policy_mgr_restart_opportunistic_timer(
13526 pHddCtx->hdd_psoc, false);
13527 if (policy_mgr_is_hw_mode_change_in_progress(
13528 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013529 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013530 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013531 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013532 hdd_err("qdf wait for event failed!!");
13533 status = -EINVAL;
13534 goto ret_status;
13535 }
13536 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013537 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013539 if (HDD_WMM_USER_MODE_NO_QOS ==
13540 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13541 /*QoS not enabled in cfg file */
13542 pRoamProfile->uapsd_mask = 0;
13543 } else {
13544 /*QoS enabled, update uapsd mask from cfg file */
13545 pRoamProfile->uapsd_mask =
13546 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13547 }
13548
13549 pRoamProfile->SSIDs.numOfSSIDs = 1;
13550 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013551 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013552 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013553 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013554 ssid, ssid_len);
13555
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013556 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013557 /* cleanup bssid hint */
13558 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13559 QDF_MAC_ADDR_SIZE);
13560 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13561 QDF_MAC_ADDR_SIZE);
13562
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013563 if (bssid) {
13564 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013565 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013566 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013567 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013568 /*
13569 * Save BSSID in seperate variable as
13570 * pRoamProfile's BSSID is getting zeroed out in the
13571 * association process. In case of join failure
13572 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013573 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013574 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013575 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013576 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013577 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013578 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13579 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013580 /*
13581 * Save BSSID in a separate variable as
13582 * pRoamProfile's BSSID is getting zeroed out in the
13583 * association process. In case of join failure
13584 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013585 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013586 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013587 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013588 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013589 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013590 }
13591
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013592 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013593 pRoamProfile->SSIDs.SSIDList->SSID.length,
13594 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13595 operatingChannel);
13596
13597 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13598 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013599 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013600 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13601 }
13602#ifdef FEATURE_WLAN_WAPI
13603 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013604 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013605 switch (pAdapter->wapi_info.wapiAuthMode) {
13606 case WAPI_AUTH_MODE_PSK:
13607 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013608 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013609 pAdapter->wapi_info.wapiAuthMode);
13610 pRoamProfile->AuthType.authType[0] =
13611 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13612 break;
13613 }
13614 case WAPI_AUTH_MODE_CERT:
13615 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013616 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617 pAdapter->wapi_info.wapiAuthMode);
13618 pRoamProfile->AuthType.authType[0] =
13619 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13620 break;
13621 }
13622 } /* End of switch */
13623 if (pAdapter->wapi_info.wapiAuthMode ==
13624 WAPI_AUTH_MODE_PSK
13625 || pAdapter->wapi_info.wapiAuthMode ==
13626 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013627 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013628 pRoamProfile->AuthType.numEntries = 1;
13629 pRoamProfile->EncryptionType.numEntries = 1;
13630 pRoamProfile->EncryptionType.encryptionType[0] =
13631 eCSR_ENCRYPT_TYPE_WPI;
13632 pRoamProfile->mcEncryptionType.numEntries = 1;
13633 pRoamProfile->mcEncryptionType.
13634 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13635 }
13636 }
Krunal Soni31949422016-07-29 17:17:53 -070013637#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013638 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639 pRoamProfile->csrPersona = pAdapter->device_mode;
13640
13641 if (operatingChannel) {
13642 pRoamProfile->ChannelInfo.ChannelList =
13643 &operatingChannel;
13644 pRoamProfile->ChannelInfo.numOfChannels = 1;
13645 } else {
13646 pRoamProfile->ChannelInfo.ChannelList = NULL;
13647 pRoamProfile->ChannelInfo.numOfChannels = 0;
13648 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013649 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013650 && operatingChannel) {
13651 /*
13652 * Need to post the IBSS power save parameters
13653 * to WMA. WMA will configure this parameters
13654 * to firmware if power save is enabled by the
13655 * firmware.
13656 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013657 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013658
Abhishek Singh471652b2017-04-14 12:28:32 +053013659 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013660 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013661 status = -EINVAL;
13662 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013663 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013664 pRoamProfile->ch_params.ch_width =
13665 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013666 /*
13667 * In IBSS mode while operating in 2.4 GHz,
13668 * the device supports only 20 MHz.
13669 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013670 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013671 pRoamProfile->ch_params.ch_width =
13672 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013673 hdd_select_cbmode(pAdapter, operatingChannel,
13674 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013675 }
13676
Abhishek Singhcfb44482017-03-10 12:42:37 +053013677 if (wlan_hdd_cfg80211_check_pmf_valid(
13678 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013679 status = -EINVAL;
13680 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013681 }
13682
Krunal Soni31949422016-07-29 17:17:53 -070013683 /*
13684 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013685 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013686 * enhancements, the supplicant is not issuing the scan command
13687 * now. So the unicast frames which are sent from the host are
13688 * not having the additional IEs. If it is P2P CLIENT and there
13689 * is no additional IE present in roamProfile, then use the
13690 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013691 */
13692
Krunal Sonib4326f22016-03-10 13:05:51 -080013693 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694 (!pRoamProfile->pAddIEScan)) {
13695 pRoamProfile->pAddIEScan =
13696 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13697 pRoamProfile->nAddIEScanLength =
13698 pAdapter->scan_info.scanAddIE.length;
13699 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013700
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013701 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13702 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013703 pRoamProfile))) {
13704 hdd_err("sap-sta conc will fail, can't allow sta");
13705 hdd_conn_set_connection_state(pAdapter,
13706 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013707 status = -ENOMEM;
13708 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013709 }
13710
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013711 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013712 if (!sme_config) {
13713 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013714 hdd_conn_set_connection_state(pAdapter,
13715 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013716 status = -ENOMEM;
13717 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013718 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013719 sme_get_config_param(pHddCtx->hHal, sme_config);
13720 /* These values are not sessionized. So, any change in these SME
13721 * configs on an older or parallel interface will affect the
13722 * cb mode. So, restoring the default INI params before starting
13723 * interfaces such as sta, cli etc.,
13724 */
13725 sme_config->csrConfig.channelBondingMode5GHz =
13726 pHddCtx->config->nChannelBondingMode5GHz;
13727 sme_config->csrConfig.channelBondingMode24GHz =
13728 pHddCtx->config->nChannelBondingMode24GHz;
13729 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013730 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013731 /*
13732 * Change conn_state to connecting before sme_roam_connect(),
13733 * because sme_roam_connect() has a direct path to call
13734 * hdd_sme_roam_callback(), which will change the conn_state
13735 * If direct path, conn_state will be accordingly changed to
13736 * NotConnected or Associated by either
13737 * hdd_association_completion_handler() or
13738 * hdd_dis_connect_handler() in sme_RoamCallback()if
13739 * sme_RomConnect is to be queued,
13740 * Connecting state will remain until it is completed.
13741 *
13742 * If connection state is not changed, connection state will
13743 * remain in eConnectionState_NotConnected state.
13744 * In hdd_association_completion_handler, "hddDisconInProgress"
13745 * is set to true if conn state is
13746 * eConnectionState_NotConnected.
13747 * If "hddDisconInProgress" is set to true then cfg80211 layer
13748 * is not informed of connect result indication which
13749 * is an issue.
13750 */
13751 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013752 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013753 hdd_conn_set_connection_state(pAdapter,
13754 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013755
Komal Seelama89be8d2016-09-29 11:09:26 +053013756 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13757 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013758 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013759 pAdapter->sessionId, pRoamProfile,
13760 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013761 if (QDF_IS_STATUS_ERROR(qdf_status))
13762 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013763
Rajeev Kumard31e1542017-01-13 14:37:42 -080013764 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013765 (QDF_STA_MODE == pAdapter->device_mode ||
13766 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013767 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013768 "qdf_status %d. -> NotConnected",
13769 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013770 /* change back to NotAssociated */
13771 hdd_conn_set_connection_state(pAdapter,
13772 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013773 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13774 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013775 }
13776
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013777 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013778 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013779
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013780 pRoamProfile->ChannelInfo.ChannelList = NULL;
13781 pRoamProfile->ChannelInfo.numOfChannels = 0;
13782
Nitesh Shah044fd672016-10-13 18:53:25 +053013783 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013784 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13785 && !policy_mgr_is_hw_dbs_2x2_capable(
13786 pHddCtx->hdd_psoc)) {
13787 policy_mgr_get_channel_from_scan_result(
13788 pHddCtx->hdd_psoc,
13789 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013790 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013791 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013792 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13793 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013794 }
13795
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013796 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013797 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013798 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013799 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013800 goto ret_status;
13801
13802conn_failure:
13803 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013804 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013805
13806ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013807 EXIT();
13808 return status;
13809}
13810
13811/**
13812 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13813 * @pAdapter: Pointer to adapter
13814 * @auth_type: Auth type
13815 *
13816 * This function is used to set the authentication type (OPEN/SHARED).
13817 *
13818 * Return: 0 for success, non-zero for failure
13819 */
13820static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13821 enum nl80211_auth_type auth_type)
13822{
13823 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13824 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013826 /*set authentication type */
13827 switch (auth_type) {
13828 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013829 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013830 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13831 break;
13832
13833 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013834 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013835 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013836 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13837 break;
13838
13839 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013840 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013841 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13842 break;
13843#ifdef FEATURE_WLAN_ESE
13844 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013845 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013846 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13847 break;
13848#endif
13849
13850 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013851 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013852 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13853 return -EINVAL;
13854 }
13855
13856 pWextState->roamProfile.AuthType.authType[0] =
13857 pHddStaCtx->conn_info.authType;
13858 return 0;
13859}
13860
13861/**
13862 * wlan_hdd_set_akm_suite() - set key management type
13863 * @pAdapter: Pointer to adapter
13864 * @key_mgmt: Key management type
13865 *
13866 * This function is used to set the key mgmt type(PSK/8021x).
13867 *
13868 * Return: 0 for success, non-zero for failure
13869 */
13870static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13871{
13872 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13873
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013874#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013875#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013876#endif
13877#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013878#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013879#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880 /*set key mgmt type */
13881 switch (key_mgmt) {
13882 case WLAN_AKM_SUITE_PSK:
13883 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013884 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013885 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013886 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13887 break;
13888
13889 case WLAN_AKM_SUITE_8021X_SHA256:
13890 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013891 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013892 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013893 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13894 break;
13895#ifdef FEATURE_WLAN_ESE
13896#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13897#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13898 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013899 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013900 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13901 break;
13902#endif
13903#ifndef WLAN_AKM_SUITE_OSEN
13904#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13905#endif
13906 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013907 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013908 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13909 break;
13910
13911 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013912 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013913 return -EINVAL;
13914
13915 }
13916 return 0;
13917}
13918
13919/**
13920 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13921 * @pAdapter: Pointer to adapter
13922 * @cipher: Cipher type
13923 * @ucast: Unicast flag
13924 *
13925 * This function is used to set the encryption type
13926 * (NONE/WEP40/WEP104/TKIP/CCMP).
13927 *
13928 * Return: 0 for success, non-zero for failure
13929 */
13930static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13931 u32 cipher, bool ucast)
13932{
13933 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13934 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13935 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13936
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013938 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013939 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13940 } else {
13941
13942 /*set encryption method */
13943 switch (cipher) {
13944 case IW_AUTH_CIPHER_NONE:
13945 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13946 break;
13947
13948 case WLAN_CIPHER_SUITE_WEP40:
13949 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13950 break;
13951
13952 case WLAN_CIPHER_SUITE_WEP104:
13953 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13954 break;
13955
13956 case WLAN_CIPHER_SUITE_TKIP:
13957 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13958 break;
13959
13960 case WLAN_CIPHER_SUITE_CCMP:
13961 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13962 break;
13963#ifdef FEATURE_WLAN_WAPI
13964 case WLAN_CIPHER_SUITE_SMS4:
13965 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13966 break;
13967#endif
13968
13969#ifdef FEATURE_WLAN_ESE
13970 case WLAN_CIPHER_SUITE_KRK:
13971 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13972 break;
13973#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13974 case WLAN_CIPHER_SUITE_BTK:
13975 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13976 break;
13977#endif
13978#endif
13979 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013980 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013981 return -EOPNOTSUPP;
13982 }
13983 }
13984
13985 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013986 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013987 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13988 pWextState->roamProfile.EncryptionType.numEntries = 1;
13989 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13990 encryptionType;
13991 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013992 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013993 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13994 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13995 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13996 encryptionType;
13997 }
13998
13999 return 0;
14000}
14001
14002/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014003 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
14004 * @wext_state: Pointer to wext state
14005 * @gen_ie: Pointer to IE data
14006 * @len: length of IE data
14007 *
14008 * Return: 0 for success, non-zero for failure
14009 */
14010static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
14011 const uint8_t *gen_ie, uint16_t len)
14012{
14013 uint16_t cur_add_ie_len =
14014 wext_state->assocAddIE.length;
14015
14016 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14017 (wext_state->assocAddIE.length + len)) {
14018 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
14019 QDF_ASSERT(0);
14020 return -ENOMEM;
14021 }
14022 memcpy(wext_state->assocAddIE.addIEdata +
14023 cur_add_ie_len, gen_ie, len);
14024 wext_state->assocAddIE.length += len;
14025
14026 wext_state->roamProfile.pAddIEAssoc =
14027 wext_state->assocAddIE.addIEdata;
14028 wext_state->roamProfile.nAddIEAssocLength =
14029 wext_state->assocAddIE.length;
14030 return 0;
14031}
14032
14033/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014034 * wlan_hdd_cfg80211_set_ie() - set IEs
14035 * @pAdapter: Pointer to adapter
14036 * @ie: Pointer ot ie
14037 * @ie: IE length
14038 *
14039 * Return: 0 for success, non-zero for failure
14040 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014041static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014042 size_t ie_len)
14043{
14044 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14045 const uint8_t *genie = ie;
14046 uint16_t remLen = ie_len;
14047#ifdef FEATURE_WLAN_WAPI
14048 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
14049 u16 *tmp;
14050 uint16_t akmsuiteCount;
14051 int *akmlist;
14052#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014053 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014054
14055 /* clear previous assocAddIE */
14056 pWextState->assocAddIE.length = 0;
14057 pWextState->roamProfile.bWPSAssociation = false;
14058 pWextState->roamProfile.bOSENAssociation = false;
14059
14060 while (remLen >= 2) {
14061 uint16_t eLen = 0;
14062 uint8_t elementId;
14063 elementId = *genie++;
14064 eLen = *genie++;
14065 remLen -= 2;
14066
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014067 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014068
14069 switch (elementId) {
14070 case DOT11F_EID_WPA:
14071 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 -070014072 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014073 return -EINVAL;
14074 } else if (0 ==
14075 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
14076 uint16_t curAddIELen =
14077 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014078 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014079
14080 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14081 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014082 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014083 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014084 return -ENOMEM;
14085 }
14086 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
14087 memcpy(pWextState->assocAddIE.addIEdata +
14088 curAddIELen, genie - 2, eLen + 2);
14089 pWextState->assocAddIE.length += eLen + 2;
14090
14091 pWextState->roamProfile.bWPSAssociation = true;
14092 pWextState->roamProfile.pAddIEAssoc =
14093 pWextState->assocAddIE.addIEdata;
14094 pWextState->roamProfile.nAddIEAssocLength =
14095 pWextState->assocAddIE.length;
14096 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014097 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014098 memset(pWextState->WPARSNIE, 0,
14099 MAX_WPA_RSN_IE_LEN);
14100 memcpy(pWextState->WPARSNIE, genie - 2,
14101 (eLen + 2));
14102 pWextState->roamProfile.pWPAReqIE =
14103 pWextState->WPARSNIE;
14104 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
14105 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
14106 P2P_OUI_TYPE_SIZE))) {
14107 uint16_t curAddIELen =
14108 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014109 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014110
14111 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14112 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014113 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014114 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014115 return -ENOMEM;
14116 }
14117 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
14118 memcpy(pWextState->assocAddIE.addIEdata +
14119 curAddIELen, genie - 2, eLen + 2);
14120 pWextState->assocAddIE.length += eLen + 2;
14121
14122 pWextState->roamProfile.pAddIEAssoc =
14123 pWextState->assocAddIE.addIEdata;
14124 pWextState->roamProfile.nAddIEAssocLength =
14125 pWextState->assocAddIE.length;
14126 }
14127#ifdef WLAN_FEATURE_WFD
14128 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
14129 WFD_OUI_TYPE_SIZE)) &&
14130 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080014131 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014132 pAdapter->device_mode)) {
14133 uint16_t curAddIELen =
14134 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014135 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014136
14137 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14138 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014139 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014140 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014141 return -ENOMEM;
14142 }
14143 /* WFD IE is saved to Additional IE ; it should
14144 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014145 * WFD IE
14146 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014147 memcpy(pWextState->assocAddIE.addIEdata +
14148 curAddIELen, genie - 2, eLen + 2);
14149 pWextState->assocAddIE.length += eLen + 2;
14150
14151 pWextState->roamProfile.pAddIEAssoc =
14152 pWextState->assocAddIE.addIEdata;
14153 pWextState->roamProfile.nAddIEAssocLength =
14154 pWextState->assocAddIE.length;
14155 }
14156#endif
14157 /* Appending HS 2.0 Indication Element in Assiciation Request */
14158 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
14159 HS20_OUI_TYPE_SIZE))) {
14160 uint16_t curAddIELen =
14161 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014162 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014163
14164 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14165 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014166 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014167 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014168 return -ENOMEM;
14169 }
14170 memcpy(pWextState->assocAddIE.addIEdata +
14171 curAddIELen, genie - 2, eLen + 2);
14172 pWextState->assocAddIE.length += eLen + 2;
14173
14174 pWextState->roamProfile.pAddIEAssoc =
14175 pWextState->assocAddIE.addIEdata;
14176 pWextState->roamProfile.nAddIEAssocLength =
14177 pWextState->assocAddIE.length;
14178 }
14179 /* Appending OSEN Information Element in Assiciation Request */
14180 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
14181 OSEN_OUI_TYPE_SIZE))) {
14182 uint16_t curAddIELen =
14183 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014184 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014185
14186 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14187 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014188 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014189 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014190 return -ENOMEM;
14191 }
14192 memcpy(pWextState->assocAddIE.addIEdata +
14193 curAddIELen, genie - 2, eLen + 2);
14194 pWextState->assocAddIE.length += eLen + 2;
14195
14196 pWextState->roamProfile.bOSENAssociation = true;
14197 pWextState->roamProfile.pAddIEAssoc =
14198 pWextState->assocAddIE.addIEdata;
14199 pWextState->roamProfile.nAddIEAssocLength =
14200 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014201 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
14202 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014203 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014204 status = wlan_hdd_add_assoc_ie(pWextState,
14205 genie - 2, eLen + 2);
14206 if (status)
14207 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208 } else {
14209 uint16_t add_ie_len =
14210 pWextState->assocAddIE.length;
14211
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014212 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014213
14214 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14215 (pWextState->assocAddIE.length + eLen)) {
14216 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014217 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014218 return -ENOMEM;
14219 }
14220
14221 memcpy(pWextState->assocAddIE.addIEdata +
14222 add_ie_len, genie - 2, eLen + 2);
14223 pWextState->assocAddIE.length += eLen + 2;
14224
14225 pWextState->roamProfile.pAddIEAssoc =
14226 pWextState->assocAddIE.addIEdata;
14227 pWextState->roamProfile.nAddIEAssocLength =
14228 pWextState->assocAddIE.length;
14229 }
14230 break;
14231 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014232 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014233 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
14234 memcpy(pWextState->WPARSNIE, genie - 2,
14235 (eLen + 2));
14236 pWextState->roamProfile.pRSNReqIE =
14237 pWextState->WPARSNIE;
14238 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
14239 break;
14240 /*
14241 * Appending Extended Capabilities with Interworking bit set
14242 * in Assoc Req.
14243 *
14244 * In assoc req this EXT Cap will only be taken into account if
14245 * interworkingService bit is set to 1. Currently
14246 * driver is only interested in interworkingService capability
14247 * from supplicant. If in future any other EXT Cap info is
14248 * required from supplicat, it needs to be handled while
14249 * sending Assoc Req in LIM.
14250 */
14251 case DOT11F_EID_EXTCAP:
14252 {
14253 uint16_t curAddIELen =
14254 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014255 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014256
14257 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14258 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014259 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014260 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014261 return -ENOMEM;
14262 }
14263 memcpy(pWextState->assocAddIE.addIEdata +
14264 curAddIELen, genie - 2, eLen + 2);
14265 pWextState->assocAddIE.length += eLen + 2;
14266
14267 pWextState->roamProfile.pAddIEAssoc =
14268 pWextState->assocAddIE.addIEdata;
14269 pWextState->roamProfile.nAddIEAssocLength =
14270 pWextState->assocAddIE.length;
14271 break;
14272 }
14273#ifdef FEATURE_WLAN_WAPI
14274 case WLAN_EID_WAPI:
14275 /* Setting WAPI Mode to ON=1 */
14276 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014277 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014278 tmp = (u16 *) ie;
14279 tmp = tmp + 2; /* Skip element Id and Len, Version */
14280 akmsuiteCount = WPA_GET_LE16(tmp);
14281 tmp = tmp + 1;
14282 akmlist = (int *)(tmp);
14283 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
14284 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
14285 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014286 hdd_err("Invalid akmSuite count: %u",
14287 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014288 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014289 return -EINVAL;
14290 }
14291
14292 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014293 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014294 pAdapter->wapi_info.wapiAuthMode =
14295 WAPI_AUTH_MODE_PSK;
14296 }
14297 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014298 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014299 pAdapter->wapi_info.wapiAuthMode =
14300 WAPI_AUTH_MODE_CERT;
14301 }
14302 break;
14303#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014304 case DOT11F_EID_SUPPOPERATINGCLASSES:
14305 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014306 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014307 status = wlan_hdd_add_assoc_ie(pWextState,
14308 genie - 2, eLen + 2);
14309 if (status)
14310 return status;
14311 break;
14312 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014313 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014314 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014315 /* when Unknown IE is received we break
14316 * and continue to the next IE in the buffer
14317 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014318 break;
14319 }
14320 genie += eLen;
14321 remLen -= eLen;
14322 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014323 return 0;
14324}
14325
14326/**
14327 * hdd_is_wpaie_present() - check for WPA ie
14328 * @ie: Pointer to ie
14329 * @ie_len: Ie length
14330 *
14331 * Parse the received IE to find the WPA IE
14332 *
14333 * Return: true if wpa ie is found else false
14334 */
14335static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
14336{
14337 uint8_t eLen = 0;
14338 uint16_t remLen = ie_len;
14339 uint8_t elementId = 0;
14340
14341 while (remLen >= 2) {
14342 elementId = *ie++;
14343 eLen = *ie++;
14344 remLen -= 2;
14345 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014346 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 return false;
14348 }
14349 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
14350 /* OUI - 0x00 0X50 0XF2
14351 * WPA Information Element - 0x01
14352 * WPA version - 0x01
14353 */
14354 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
14355 return true;
14356 }
14357 ie += eLen;
14358 remLen -= eLen;
14359 }
14360 return false;
14361}
14362
14363/**
14364 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
14365 * @pAdapter: Pointer to adapter
14366 * @req: Pointer to security parameters
14367 *
14368 * Return: 0 for success, non-zero for failure
14369 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014370static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
14371 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014372{
14373 int status = 0;
14374 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14375 ENTER();
14376
14377 /*set wpa version */
14378 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
14379
14380 if (req->crypto.wpa_versions) {
14381 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
14382 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
14383 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
14384 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14385 }
14386 }
14387
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014388 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014389
14390 /*set authentication type */
14391 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
14392
14393 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014394 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014395 return status;
14396 }
14397
14398 /*set key mgmt type */
14399 if (req->crypto.n_akm_suites) {
14400 status =
14401 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
14402 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014403 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014404 return status;
14405 }
14406 }
14407
14408 /*set pairwise cipher type */
14409 if (req->crypto.n_ciphers_pairwise) {
14410 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
14411 req->crypto.
14412 ciphers_pairwise[0],
14413 true);
14414 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014415 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014416 return status;
14417 }
14418 } else {
14419 /*Reset previous cipher suite to none */
14420 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14421 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014422 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014423 return status;
14424 }
14425 }
14426
14427 /*set group cipher type */
14428 status =
14429 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14430 false);
14431
14432 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014433 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014434 return status;
14435 }
14436#ifdef WLAN_FEATURE_11W
14437 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14438#endif
14439
14440 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14441 if (req->ie_len) {
14442 status =
14443 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14444 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014445 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014446 return status;
14447 }
14448 }
14449
14450 /*incase of WEP set default key information */
14451 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014452 u8 key_len = req->key_len;
14453 u8 key_idx = req->key_idx;
14454
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014455 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14456 || (WLAN_CIPHER_SUITE_WEP104 ==
14457 req->crypto.ciphers_pairwise[0])
14458 ) {
14459 if (IW_AUTH_KEY_MGMT_802_1X
14460 ==
14461 (pWextState->
14462 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014463 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014464 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014465 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014466
Jeff Johnson68755312017-02-10 11:46:55 -080014467 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14468 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014469 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014470 key_idx, key_len);
14471 qdf_mem_copy(&pWextState->roamProfile.
14472 Keys.
14473 KeyMaterial[key_idx][0],
14474 req->key, key_len);
14475 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014476 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014477 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014478 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014479 }
14480 }
14481 }
14482
14483 return status;
14484}
14485
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014486int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014487{
14488 unsigned long rc;
14489 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014490 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014491 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014492
14493 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014494 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14495 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014496 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014497 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14498 }
14499 /*
14500 * If firmware has already started roaming process, driver
14501 * needs to defer the processing of this disconnect request.
14502 *
14503 */
14504 if (hdd_is_roaming_in_progress(pAdapter)) {
14505 /*
14506 * Defer the disconnect action until firmware roaming
14507 * result is received. If STA is in connected state after
14508 * that, send the disconnect command to CSR, otherwise
14509 * CSR would have already sent disconnect event to upper
14510 * layer.
14511 */
14512
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014513 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014514 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14515 pAdapter->cfg80211_disconnect_reason =
14516 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14517 return 0;
14518 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014519
Jeff Johnson9edf9572016-10-03 15:24:49 -070014520 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014521 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14522 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14523 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014524 hdd_conn_set_connection_state(pAdapter,
14525 eConnectionState_Disconnecting);
14526 /* Issue disconnect to CSR */
14527 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014528
14529 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14530 pAdapter->sessionId,
14531 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14532 /*
14533 * Wait here instead of returning directly, this will block the
14534 * next connect command and allow processing of the scan for
14535 * ssid and the previous connect command in CSR. Else we might
14536 * hit some race conditions leading to SME and HDD out of sync.
14537 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014538 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014539 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014540 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014541 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014542 (int)status);
14543 pHddStaCtx->staDebugState = status;
14544 result = -EINVAL;
14545 goto disconnected;
14546 }
14547
14548 rc = wait_for_completion_timeout(
14549 &pAdapter->disconnect_comp_var,
14550 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014551 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014552 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014553 pAdapter->sessionId, pHddStaCtx->staDebugState);
14554 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014555 }
14556 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014557 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014558 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014559 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014560 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014561 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014562 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014563 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014564 }
14565 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014566disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014567 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14568 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014569}
14570
14571/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014572 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14573 * @adapter: Pointer to the HDD adapter
14574 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014575 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014576 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014577 * This function will start reassociation if prev_bssid is set and bssid/
14578 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014579 *
Naveen Rawat07332902016-07-27 09:13:17 -070014580 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014581 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014582#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14583 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014584static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14585 struct cfg80211_connect_params *req,
14586 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014587{
Naveen Rawat07332902016-07-27 09:13:17 -070014588 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014589 const uint8_t *bssid = NULL;
14590 uint16_t channel = 0;
Arif Hussain43354e62017-05-24 11:24:25 -070014591 hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014592
14593 if (req->bssid)
14594 bssid = req->bssid;
14595 else if (req->bssid_hint)
14596 bssid = req->bssid_hint;
14597
14598 if (req->channel)
14599 channel = req->channel->hw_value;
14600 else if (req->channel_hint)
14601 channel = req->channel_hint->hw_value;
14602
14603 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014604 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014605 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014606 channel, MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070014607 /*
14608 * Save BSSID in a separate variable as
14609 * pRoamProfile's BSSID is getting zeroed out in the
14610 * association process. In case of join failure
14611 * we should send valid BSSID to supplicant
14612 */
14613 qdf_mem_copy(wext_state->req_bssId.bytes, bssid,
14614 QDF_MAC_ADDR_SIZE);
14615
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014616 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014617 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014618 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014619 }
Naveen Rawat07332902016-07-27 09:13:17 -070014620 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014621}
14622#else
Naveen Rawat07332902016-07-27 09:13:17 -070014623static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14624 struct cfg80211_connect_params *req,
14625 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014626{
Naveen Rawat07332902016-07-27 09:13:17 -070014627 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014628}
14629#endif
14630
14631/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014632 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14633 * @wiphy: Pointer to wiphy
14634 * @dev: Pointer to network device
14635 * @req: Pointer to cfg80211 connect request
14636 *
14637 * This function is used to start the association process
14638 *
14639 * Return: 0 for success, non-zero for failure
14640 */
14641static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14642 struct net_device *ndev,
14643 struct cfg80211_connect_params *req)
14644{
14645 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014646 u16 channel;
14647#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14648 const u8 *bssid_hint = req->bssid_hint;
14649#else
14650 const u8 *bssid_hint = NULL;
14651#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014652 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14653 hdd_context_t *pHddCtx;
14654
14655 ENTER();
14656
Anurag Chouhan6d760662016-02-20 16:05:43 +053014657 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014658 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014659 return -EINVAL;
14660 }
14661
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014662 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14663 hdd_err("invalid session id: %d", pAdapter->sessionId);
14664 return -EINVAL;
14665 }
14666
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014667 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014668 TRACE_CODE_HDD_CFG80211_CONNECT,
14669 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014670 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014671 hdd_device_mode_to_string(pAdapter->device_mode),
14672 pAdapter->device_mode);
14673
Krunal Sonib4326f22016-03-10 13:05:51 -080014674 if (pAdapter->device_mode != QDF_STA_MODE &&
14675 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014676 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014677 hdd_device_mode_to_string(pAdapter->device_mode),
14678 pAdapter->device_mode);
14679 return -EINVAL;
14680 }
14681
14682 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14683 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014684 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014685 return -EINVAL;
14686 }
14687
14688 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014689 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014690 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014691
Naveen Rawat07332902016-07-27 09:13:17 -070014692 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014693 return status;
14694
Agrawal Ashishf156e942016-08-04 14:54:47 +053014695 /* Try disconnecting if already in connected state */
14696 status = wlan_hdd_try_disconnect(pAdapter);
14697 if (0 > status) {
14698 hdd_err("Failed to disconnect the existing connection");
14699 return -EALREADY;
14700 }
14701
14702 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014703 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014704 bool ok;
14705
14706 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14707 pHddCtx->hdd_psoc,
14708 req->channel->hw_value,
14709 &ok)) {
14710 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14711 req->channel->hw_value);
14712 return -EINVAL;
14713 }
14714 /**
14715 * Send connection timedout, so that Android framework does not
14716 * blacklist us.
14717 */
14718 if (!ok) {
14719 struct ieee80211_channel *chan =
14720 __ieee80211_get_channel(wiphy,
14721 wlan_chan_to_freq(req->channel->hw_value));
14722 struct cfg80211_bss *bss;
14723
14724 hdd_warn("Channel:%d not OK for DNBS",
14725 req->channel->hw_value);
14726 if (chan) {
14727 bss = hdd_cfg80211_get_bss(wiphy,
14728 chan,
14729 req->bssid, req->ssid,
14730 req->ssid_len);
14731 if (bss) {
14732 cfg80211_assoc_timeout(ndev, bss);
14733 return -ETIMEDOUT;
14734 }
14735 }
14736 return -EINVAL;
14737 }
14738
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014739 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14740 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014741 pAdapter->device_mode),
14742 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014743 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014744 return -ECONNREFUSED;
14745 }
14746 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014747 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14748 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014749 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014750 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014751 return -ECONNREFUSED;
14752 }
14753 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014754
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014755 /*initialise security parameters */
14756 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14757
14758 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014759 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014760 return status;
14761 }
14762
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014763 if (req->channel)
14764 channel = req->channel->hw_value;
14765 else
14766 channel = 0;
14767 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14768 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014769 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014770 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014771 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014772 return status;
14773 }
14774 EXIT();
14775 return status;
14776}
14777
14778/**
14779 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14780 * @wiphy: Pointer to wiphy
14781 * @dev: Pointer to network device
14782 * @req: Pointer to cfg80211 connect request
14783 *
14784 * Return: 0 for success, non-zero for failure
14785 */
14786static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14787 struct net_device *ndev,
14788 struct cfg80211_connect_params *req)
14789{
14790 int ret;
14791 cds_ssr_protect(__func__);
14792 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14793 cds_ssr_unprotect(__func__);
14794
14795 return ret;
14796}
14797
14798/**
14799 * wlan_hdd_disconnect() - hdd disconnect api
14800 * @pAdapter: Pointer to adapter
14801 * @reason: Disconnect reason code
14802 *
14803 * This function is used to issue a disconnect request to SME
14804 *
14805 * Return: 0 for success, non-zero for failure
14806 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014807static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014808{
14809 int status, result = 0;
14810 unsigned long rc;
14811 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14812 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014813 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014814 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014815
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014816 ENTER();
14817
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014818 status = wlan_hdd_validate_context(pHddCtx);
14819
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014820 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014821 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014822 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014823 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014824 status = sme_stop_roaming(hal, pAdapter->sessionId,
14825 eCsrHddIssued);
14826 }
14827 /*
14828 * If firmware has already started roaming process, driver
14829 * needs to defer the processing of this disconnect request.
14830 */
14831 if (hdd_is_roaming_in_progress(pAdapter)) {
14832 /*
14833 * Defer the disconnect action until firmware roaming
14834 * result is received. If STA is in connected state after
14835 * that, send the disconnect command to CSR, otherwise
14836 * CSR would have already sent disconnect event to upper
14837 * layer.
14838 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014839 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014840 pAdapter->defer_disconnect =
14841 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14842 pAdapter->cfg80211_disconnect_reason = reason;
14843 return 0;
14844 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014845
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014846 prev_conn_state = pHddStaCtx->conn_info.connState;
14847
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014848 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014849 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014850 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014851 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014852 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014853 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14854 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14855
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014856 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014857
14858 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14859 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014860 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14861 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014862 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014863 result = 0;
14864 goto disconnected;
14865 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14866 /*
14867 * Wait here instead of returning directly, this will block the
14868 * next connect command and allow processing of the scan for
14869 * ssid and the previous connect command in CSR. Else we might
14870 * hit some race conditions leading to SME and HDD out of sync.
14871 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014872 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014873 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014874 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014875 pHddStaCtx->staDebugState = status;
14876 result = -EINVAL;
14877 goto disconnected;
14878 }
14879 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14880 msecs_to_jiffies
14881 (WLAN_WAIT_TIME_DISCONNECT));
14882
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014883 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014884 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014885 result = -ETIMEDOUT;
14886 }
14887disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014888 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14889#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14890 /* Sending disconnect event to userspace for kernel version < 3.11
14891 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14892 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014893 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014894 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14895 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014896#endif
14897
14898 return result;
14899}
14900
14901/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014902 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14903 * @reason: ieee80211 reason code.
14904 *
14905 * This utility function helps log string conversion of reason code.
14906 *
14907 * Return: string conversion of reason code, if match found;
14908 * "Unknown" otherwise.
14909 */
14910static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14911{
14912 switch (reason) {
14913 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14914 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14915 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14916 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14917 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14918 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14919 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14920 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14921 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14922 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14923 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14924 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14925 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14926 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14927 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14928 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14929 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14930 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14931 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14932 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14933 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14934 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14935 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14936 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14937 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14938 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14939 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14940 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14941 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14942 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14943 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14944 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14945 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14946 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14947 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14948 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14949 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14950 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14951 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14952 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14953 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14954 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14955 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14956 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14957 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14958 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14959 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14960 default:
14961 return "Unknown";
14962 }
14963}
14964
14965/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014966 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14967 * @wiphy: Pointer to wiphy
14968 * @dev: Pointer to network device
14969 * @reason: Disconnect reason code
14970 *
14971 * This function is used to issue a disconnect request to SME
14972 *
14973 * Return: 0 for success, non-zero for failure
14974 */
14975static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14976 struct net_device *dev, u16 reason)
14977{
14978 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14979 int status;
14980 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14981 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14982#ifdef FEATURE_WLAN_TDLS
14983 uint8_t staIdx;
14984#endif
14985
14986 ENTER();
14987
Anurag Chouhan6d760662016-02-20 16:05:43 +053014988 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014989 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014990 return -EINVAL;
14991 }
14992
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014993 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014994 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014995 return -EINVAL;
14996 }
14997
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014998 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014999 TRACE_CODE_HDD_CFG80211_DISCONNECT,
15000 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015001 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015002 hdd_device_mode_to_string(pAdapter->device_mode),
15003 pAdapter->device_mode, reason);
15004
15005 status = wlan_hdd_validate_context(pHddCtx);
15006
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015007 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015008 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015009
15010 /* Issue disconnect request to SME, if station is in connected state */
15011 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
15012 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
15013 eCsrRoamDisconnectReason reasonCode =
15014 eCSR_DISCONNECT_REASON_UNSPECIFIED;
15015 hdd_scaninfo_t *pScanInfo;
15016
15017 switch (reason) {
15018 case WLAN_REASON_MIC_FAILURE:
15019 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
15020 break;
15021
15022 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
15023 case WLAN_REASON_DISASSOC_AP_BUSY:
15024 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
15025 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
15026 break;
15027
15028 case WLAN_REASON_PREV_AUTH_NOT_VALID:
15029 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
15030 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
15031 break;
15032
15033 case WLAN_REASON_DEAUTH_LEAVING:
15034 reasonCode =
15035 pHddCtx->config->
15036 gEnableDeauthToDisassocMap ?
15037 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
15038 eCSR_DISCONNECT_REASON_DEAUTH;
15039 break;
15040 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
15041 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
15042 break;
15043 default:
15044 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
15045 break;
15046 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015047 pScanInfo = &pAdapter->scan_info;
15048 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015049 hdd_debug("Disconnect is in progress, Aborting Scan");
Abhishek Singh69ccb512017-04-25 11:58:16 +053015050 wlan_abort_scan(pHddCtx->hdd_pdev, INVAL_PDEV_ID,
15051 pAdapter->sessionId, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015052 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053015053 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015054#ifdef FEATURE_WLAN_TDLS
15055 /* First clean up the tdls peers if any */
15056 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
15057 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
15058 pAdapter->sessionId)
15059 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
15060 uint8_t *mac;
15061 mac =
15062 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015063 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015064 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015065 pHddCtx->tdlsConnInfo[staIdx].staId,
15066 pAdapter->sessionId,
15067 MAC_ADDR_ARRAY(mac));
15068 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
15069 (pAdapter),
15070 pAdapter->sessionId, mac);
15071 }
15072 }
Kabilan Kannanaad2f032017-05-08 13:25:37 -070015073 hdd_notify_sta_disconnect(pAdapter->sessionId,
15074 true, pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015075#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070015076 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
15077 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015078 status = wlan_hdd_disconnect(pAdapter, reasonCode);
15079 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015080 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015081 return -EINVAL;
15082 }
15083 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015084 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015085 pHddStaCtx->conn_info.connState);
15086 }
15087
15088 return status;
15089}
15090
15091/**
15092 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
15093 * @wiphy: Pointer to wiphy
15094 * @dev: Pointer to network device
15095 * @reason: Disconnect reason code
15096 *
15097 * Return: 0 for success, non-zero for failure
15098 */
15099static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
15100 struct net_device *dev, u16 reason)
15101{
15102 int ret;
15103 cds_ssr_protect(__func__);
15104 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
15105 cds_ssr_unprotect(__func__);
15106
15107 return ret;
15108}
15109
15110/**
15111 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
15112 * @pAdapter: Pointer to adapter
15113 * @param: Pointer to IBSS parameters
15114 *
15115 * This function is used to initialize the security settings in IBSS mode
15116 *
15117 * Return: 0 for success, non-zero for failure
15118 */
15119static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
15120 struct cfg80211_ibss_params
15121 *params)
15122{
15123 int status = 0;
15124 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15125 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
15126 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15127
15128 ENTER();
15129
15130 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015131 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015132 pHddStaCtx->ibss_enc_key_installed = 0;
15133
15134 if (params->ie_len && (NULL != params->ie)) {
15135 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
15136 params->ie_len, WLAN_EID_RSN)) {
15137 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
15138 encryptionType = eCSR_ENCRYPT_TYPE_AES;
15139 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
15140 tDot11fIEWPA dot11WPAIE;
15141 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15142 u8 *ie;
15143
15144 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
15145 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
15146 params->ie_len,
15147 DOT11F_EID_WPA);
15148 if (NULL != ie) {
15149 pWextState->wpaVersion =
15150 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015151 /* Unpack the WPA IE
15152 * Skip past the EID byte and length byte
15153 * and four byte WiFi OUI
15154 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015155 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053015156 &ie[2 + 4], ie[1] - 4,
15157 &dot11WPAIE, false);
15158 /*
15159 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015160 * encType for unicast cipher for
15161 * wpa-none is none
15162 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015163 encryptionType =
15164 hdd_translate_wpa_to_csr_encryption_type
15165 (dot11WPAIE.multicast_cipher);
15166 }
15167 }
15168
15169 status =
15170 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
15171 params->ie_len);
15172
15173 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015174 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015175 return status;
15176 }
15177 }
15178
15179 pWextState->roamProfile.AuthType.authType[0] =
15180 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
15181
15182 if (params->privacy) {
15183 /* Security enabled IBSS, At this time there is no information
15184 * available about the security paramters, so initialise the
15185 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
15186 * The correct security parameters will be updated later in
15187 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
15188 * set inorder enable privacy bit in beacons
15189 */
15190
15191 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
15192 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015193 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015194 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
15195 pWextState->roamProfile.EncryptionType.numEntries = 1;
15196 pWextState->roamProfile.EncryptionType.encryptionType[0] =
15197 encryptionType;
15198 return status;
15199}
15200
15201/**
15202 * __wlan_hdd_cfg80211_join_ibss() - join ibss
15203 * @wiphy: Pointer to wiphy
15204 * @dev: Pointer to network device
15205 * @param: Pointer to IBSS join parameters
15206 *
15207 * This function is used to create/join an IBSS network
15208 *
15209 * Return: 0 for success, non-zero for failure
15210 */
15211static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15212 struct net_device *dev,
15213 struct cfg80211_ibss_params *params)
15214{
15215 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15216 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15217 tCsrRoamProfile *pRoamProfile;
15218 int status;
15219 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15220 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053015221 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015222 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015223
15224 ENTER();
15225
Anurag Chouhan6d760662016-02-20 16:05:43 +053015226 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015227 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015228 return -EINVAL;
15229 }
15230
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015231 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015232 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015233 return -EINVAL;
15234 }
15235
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015236 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015237 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
15238 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015239 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015240 hdd_device_mode_to_string(pAdapter->device_mode),
15241 pAdapter->device_mode);
15242
15243 status = wlan_hdd_validate_context(pHddCtx);
15244
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015245 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015247
15248 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053015249 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015250 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
15251 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
15252 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15253 int indx;
15254
15255 /* Get channel number */
15256 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015257 params->
15258 chandef.
15259 chan->
15260 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015261
15262 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
15263 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015264 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015265 return -EOPNOTSUPP;
15266 }
15267
15268 for (indx = 0; indx < numChans; indx++) {
15269 if (channelNum == validChan[indx]) {
15270 break;
15271 }
15272 }
15273 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015274 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015275 return -EINVAL;
15276 }
15277 }
15278
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015279 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
15280 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015281 hdd_err("This concurrency combination is not allowed");
15282 return -ECONNREFUSED;
15283 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015284
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015285 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015286 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015287 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015288
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015289 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
15290 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070015291 SIR_UPDATE_REASON_JOIN_IBSS);
15292 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015293 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070015294 return -EINVAL;
15295 }
15296
15297 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015298 status = policy_mgr_wait_for_connection_update(
15299 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015300 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015301 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015302 return -EINVAL;
15303 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 }
15305
15306 /*Try disconnecting if already in connected state */
15307 status = wlan_hdd_try_disconnect(pAdapter);
15308 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015309 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015310 return -EALREADY;
15311 }
15312
15313 pRoamProfile = &pWextState->roamProfile;
15314
15315 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015316 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015317 return -EINVAL;
15318 }
15319
15320 /* enable selected protection checks in IBSS mode */
15321 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
15322
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015323 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015324 WNI_CFG_IBSS_ATIM_WIN_SIZE,
15325 pHddCtx->config->
15326 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015327 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015328 }
15329
15330 /* BSSID is provided by upper layers hence no need to AUTO generate */
15331 if (NULL != params->bssid) {
15332 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015333 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015334 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015335 return -EIO;
15336 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015337 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015338 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
15339 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015340 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015341 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015342 return -EIO;
15343 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053015344 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015345 }
15346 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
15347 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
15348 pRoamProfile->beaconInterval = params->beacon_interval;
15349 else {
15350 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015351 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015352 params->beacon_interval, pRoamProfile->beaconInterval);
15353 }
15354
15355 /* Set Channel */
15356 if (channelNum) {
15357 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015358 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015359 pRoamProfile->ChannelInfo.numOfChannels = 1;
15360 pHddStaCtx->conn_info.operationChannel = channelNum;
15361 pRoamProfile->ChannelInfo.ChannelList =
15362 &pHddStaCtx->conn_info.operationChannel;
15363 }
15364
15365 /* Initialize security parameters */
15366 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
15367 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015368 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015369 return status;
15370 }
15371
15372 /* Issue connect start */
15373 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
15374 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015375 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015376 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015377 operationChannel,
15378 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015379
15380 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015381 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015382 return status;
15383 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015384 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015385 return 0;
15386}
15387
15388/**
15389 * wlan_hdd_cfg80211_join_ibss() - join ibss
15390 * @wiphy: Pointer to wiphy
15391 * @dev: Pointer to network device
15392 * @param: Pointer to IBSS join parameters
15393 *
15394 * This function is used to create/join an IBSS network
15395 *
15396 * Return: 0 for success, non-zero for failure
15397 */
15398static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15399 struct net_device *dev,
15400 struct cfg80211_ibss_params *params)
15401{
15402 int ret = 0;
15403
15404 cds_ssr_protect(__func__);
15405 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
15406 cds_ssr_unprotect(__func__);
15407
15408 return ret;
15409}
15410
15411/**
15412 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
15413 * @wiphy: Pointer to wiphy
15414 * @dev: Pointer to network device
15415 *
15416 * This function is used to leave an IBSS network
15417 *
15418 * Return: 0 for success, non-zero for failure
15419 */
15420static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15421 struct net_device *dev)
15422{
15423 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15424 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15425 tCsrRoamProfile *pRoamProfile;
15426 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15427 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015428 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015429 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015430 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015431
15432 ENTER();
15433
Anurag Chouhan6d760662016-02-20 16:05:43 +053015434 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015435 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015436 return -EINVAL;
15437 }
15438
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015439 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015440 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015441 return -EINVAL;
15442 }
15443
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015444 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015445 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15446 pAdapter->sessionId,
15447 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15448 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015449 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015450 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015451
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015452 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015453 hdd_device_mode_to_string(pAdapter->device_mode),
15454 pAdapter->device_mode);
15455 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015456 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015457 return -EIO;
15458 }
15459
15460 pRoamProfile = &pWextState->roamProfile;
15461
15462 /* Issue disconnect only if interface type is set to IBSS */
15463 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015464 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015465 return -EINVAL;
15466 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015467 /* Clearing add IE of beacon */
15468 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15469 sizeof(tSirMacAddr));
15470 updateIE.smeSessionId = pAdapter->sessionId;
15471 updateIE.ieBufferlength = 0;
15472 updateIE.pAdditionIEBuffer = NULL;
15473 updateIE.append = true;
15474 updateIE.notify = true;
15475 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15476 &updateIE,
15477 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015478 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015479 }
15480
15481 /* Reset WNI_CFG_PROBE_RSP Flags */
15482 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015483
15484 /* Issue Disconnect request */
15485 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15486 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15487 pAdapter->sessionId,
15488 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015489 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015490 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491 hal_status);
15492 return -EAGAIN;
15493 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015494
15495 /* wait for mc thread to cleanup and then return to upper stack
15496 * so by the time upper layer calls the change interface, we are
15497 * all set to proceed further
15498 */
15499 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15500 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15501 if (!rc) {
15502 hdd_err("Failed to disconnect, timed out");
15503 return -ETIMEDOUT;
15504 }
15505
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015506 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015507 return 0;
15508}
15509
15510/**
15511 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15512 * @wiphy: Pointer to wiphy
15513 * @dev: Pointer to network device
15514 *
15515 * This function is used to leave an IBSS network
15516 *
15517 * Return: 0 for success, non-zero for failure
15518 */
15519static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15520 struct net_device *dev)
15521{
15522 int ret = 0;
15523
15524 cds_ssr_protect(__func__);
15525 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15526 cds_ssr_unprotect(__func__);
15527
15528 return ret;
15529}
15530
15531/**
15532 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15533 * @wiphy: Pointer to wiphy
15534 * @changed: Parameters changed
15535 *
15536 * This function is used to set the phy parameters. RTS Threshold/FRAG
15537 * Threshold/Retry Count etc.
15538 *
15539 * Return: 0 for success, non-zero for failure
15540 */
15541static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15542 u32 changed)
15543{
15544 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15545 tHalHandle hHal = pHddCtx->hHal;
15546 int status;
15547
15548 ENTER();
15549
Anurag Chouhan6d760662016-02-20 16:05:43 +053015550 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015551 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015552 return -EINVAL;
15553 }
15554
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015555 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015556 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15557 NO_SESSION, wiphy->rts_threshold));
15558 status = wlan_hdd_validate_context(pHddCtx);
15559
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015560 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015561 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015562
15563 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15564 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15565 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15566
15567 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15568 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015569 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015570 rts_threshold);
15571 return -EINVAL;
15572 }
15573
15574 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15575 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015576 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 rts_threshold);
15578 return -EIO;
15579 }
15580
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015581 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015582 }
15583
15584 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15585 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15586 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15587 wiphy->frag_threshold;
15588
15589 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15590 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015591 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015592 frag_threshold);
15593 return -EINVAL;
15594 }
15595
15596 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15597 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015598 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015599 frag_threshold);
15600 return -EIO;
15601 }
15602
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015603 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015604 }
15605
15606 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15607 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15608 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15609 wiphy->retry_short : wiphy->retry_long;
15610
15611 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15612 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015613 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015614 return -EINVAL;
15615 }
15616
15617 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15618 if (0 != sme_cfg_set_int(hHal,
15619 WNI_CFG_LONG_RETRY_LIMIT,
15620 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015621 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015622 retry_value);
15623 return -EIO;
15624 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015625 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015626 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15627 if (0 != sme_cfg_set_int(hHal,
15628 WNI_CFG_SHORT_RETRY_LIMIT,
15629 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015630 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015631 retry_value);
15632 return -EIO;
15633 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015634 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015635 }
15636 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015637 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015638 return 0;
15639}
15640
15641/**
15642 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15643 * @wiphy: Pointer to wiphy
15644 * @changed: Parameters changed
15645 *
15646 * Return: 0 for success, non-zero for failure
15647 */
15648static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15649{
15650 int ret;
15651
15652 cds_ssr_protect(__func__);
15653 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15654 cds_ssr_unprotect(__func__);
15655
15656 return ret;
15657}
15658
15659/**
15660 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15661 * key
15662 * @wiphy: Pointer to wiphy
15663 * @dev: Pointer to network device
15664 * @key_index: Key index
15665 *
15666 * Return: 0
15667 */
15668static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15669 struct net_device *netdev,
15670 u8 key_index)
15671{
15672 ENTER();
15673 return 0;
15674}
15675
15676/**
15677 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15678 * wlan_hdd_set_default_mgmt_key
15679 * @wiphy: pointer to wiphy
15680 * @netdev: pointer to net_device structure
15681 * @key_index: key index
15682 *
15683 * Return: 0 on success, error number on failure
15684 */
15685static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15686 struct net_device *netdev,
15687 u8 key_index)
15688{
15689 int ret;
15690
15691 cds_ssr_protect(__func__);
15692 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15693 cds_ssr_unprotect(__func__);
15694
15695 return ret;
15696}
15697
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015698/**
15699 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15700 * @wiphy: Pointer to wiphy
15701 * @dev: Pointer to network device
15702 * @params: Pointer to tx queue parameters
15703 *
15704 * Return: 0
15705 */
15706static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15707 struct net_device *dev,
15708 struct ieee80211_txq_params *params)
15709{
15710 ENTER();
15711 return 0;
15712}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015713
15714/**
15715 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15716 * @wiphy: pointer to wiphy
15717 * @netdev: pointer to net_device structure
15718 * @params: pointer to ieee80211_txq_params
15719 *
15720 * Return: 0 on success, error number on failure
15721 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015722static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15723 struct net_device *dev,
15724 struct ieee80211_txq_params *params)
15725{
15726 int ret;
15727
15728 cds_ssr_protect(__func__);
15729 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15730 cds_ssr_unprotect(__func__);
15731
15732 return ret;
15733}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015734
15735/**
15736 * __wlan_hdd_cfg80211_del_station() - delete station v2
15737 * @wiphy: Pointer to wiphy
15738 * @param: Pointer to delete station parameter
15739 *
15740 * Return: 0 for success, non-zero for failure
15741 */
15742static
15743int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15744 struct net_device *dev,
15745 struct tagCsrDelStaParams *pDelStaParams)
15746{
15747 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15748 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015749 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015750 hdd_hostapd_state_t *hapd_state;
15751 int status;
15752 uint8_t staId;
15753 uint8_t *mac;
15754
15755 ENTER();
15756
Anurag Chouhan6d760662016-02-20 16:05:43 +053015757 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015758 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015759 return -EINVAL;
15760 }
15761
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015762 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015763 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015764 return -EINVAL;
15765 }
15766
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015767 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015768 TRACE_CODE_HDD_CFG80211_DEL_STA,
15769 pAdapter->sessionId, pAdapter->device_mode));
15770
15771 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15772 status = wlan_hdd_validate_context(pHddCtx);
15773
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015774 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015775 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015776
15777 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15778
Krunal Sonib4326f22016-03-10 13:05:51 -080015779 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15780 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015781
15782 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15783 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015784 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015785 return 0;
15786 }
15787
Anurag Chouhanc5548422016-02-24 18:33:27 +053015788 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015789 uint16_t i;
15790 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15791 if ((pAdapter->aStaInfo[i].isUsed) &&
15792 (!pAdapter->aStaInfo[i].
15793 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015794 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015795 mac,
15796 pAdapter->aStaInfo[i].
15797 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015798 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015799 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15800 hdd_ipa_wlan_evt(pAdapter,
15801 pAdapter->
15802 aStaInfo[i].
15803 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015804 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015805 mac);
15806 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015807 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015808 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015809 MAC_ADDR_ARRAY(mac));
15810
15811 if (pHddCtx->dev_dfs_cac_status ==
15812 DFS_CAC_IN_PROGRESS)
15813 goto fn_end;
15814
Wei Song2f76f642016-11-18 16:32:53 +080015815 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015816 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015817 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015818 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015819 hdd_softap_sta_deauth(pAdapter,
15820 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015821 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015822 pAdapter->aStaInfo[i].
15823 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015824 qdf_status =
15825 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015826 &hapd_state->
15827 qdf_sta_disassoc_event,
15828 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015829 if (!QDF_IS_STATUS_SUCCESS(
15830 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015831 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015832 }
15833 }
15834 }
15835 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015836 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015837 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015838 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015839 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015840 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015841 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015842 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015843 MAC_ADDR_ARRAY(mac));
15844 return -ENOENT;
15845 }
15846
15847 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15848 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015849 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015850 }
15851
15852 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15853 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015854 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015855 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015856 MAC_ADDR_ARRAY(mac));
15857 return -ENOENT;
15858 }
15859
15860 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15861
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015862 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015863 MAC_ADDR_ARRAY(mac));
15864
15865 /* Case: SAP in ACS selected DFS ch and client connected
15866 * Now Radar detected. Then if random channel is another
15867 * DFS ch then new CAC is initiated and no TX allowed.
15868 * So do not send any mgmt frames as it will timeout
15869 * during CAC.
15870 */
15871
15872 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15873 goto fn_end;
15874
Wei Song2f76f642016-11-18 16:32:53 +080015875 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015876 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15877 (pAdapter), pAdapter->sessionId,
15878 (uint8_t *)&pDelStaParams->peerMacAddr,
15879 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015880 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015881 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015882 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015883 pAdapter->aStaInfo[staId].isDeauthInProgress =
15884 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015885 hdd_debug("STA removal failed for ::"
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 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015890 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015891 &hapd_state->
15892 qdf_sta_disassoc_event,
15893 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015894 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015895 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015896 }
15897 }
15898 }
15899
15900fn_end:
15901 EXIT();
15902 return 0;
15903}
15904
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015905#if defined(USE_CFG80211_DEL_STA_V2)
15906/**
15907 * wlan_hdd_del_station() - delete station wrapper
15908 * @adapter: pointer to the hdd adapter
15909 *
15910 * Return: None
15911 */
15912void wlan_hdd_del_station(hdd_adapter_t *adapter)
15913{
15914 struct station_del_parameters del_sta;
15915 del_sta.mac = NULL;
15916 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15917 del_sta.reason_code = eCsrForcedDeauthSta;
15918
15919 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15920 &del_sta);
15921}
15922#else
15923void wlan_hdd_del_station(hdd_adapter_t *adapter)
15924{
15925 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15926}
15927#endif
15928
15929#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015930/**
15931 * wlan_hdd_cfg80211_del_station() - delete station v2
15932 * @wiphy: Pointer to wiphy
15933 * @param: Pointer to delete station parameter
15934 *
15935 * Return: 0 for success, non-zero for failure
15936 */
15937int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15938 struct net_device *dev,
15939 struct station_del_parameters *param)
15940#else
15941/**
15942 * wlan_hdd_cfg80211_del_station() - delete station
15943 * @wiphy: Pointer to wiphy
15944 * @mac: Pointer to station mac address
15945 *
15946 * Return: 0 for success, non-zero for failure
15947 */
15948#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15949int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15950 struct net_device *dev,
15951 const uint8_t *mac)
15952#else
15953int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15954 struct net_device *dev,
15955 uint8_t *mac)
15956#endif
15957#endif
15958{
15959 int ret;
15960 struct tagCsrDelStaParams delStaParams;
15961
15962 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015963#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015964 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015965 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015966 return -EINVAL;
15967 }
15968 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15969 param->subtype, &delStaParams);
15970#else
15971 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15972 (SIR_MAC_MGMT_DEAUTH >> 4),
15973 &delStaParams);
15974#endif
15975 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15976 cds_ssr_unprotect(__func__);
15977
15978 return ret;
15979}
15980
15981/**
15982 * __wlan_hdd_cfg80211_add_station() - add station
15983 * @wiphy: Pointer to wiphy
15984 * @mac: Pointer to station mac address
15985 * @pmksa: Pointer to add station parameter
15986 *
15987 * Return: 0 for success, non-zero for failure
15988 */
15989static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15990 struct net_device *dev,
15991 const uint8_t *mac,
15992 struct station_parameters *params)
15993{
15994 int status = -EPERM;
15995#ifdef FEATURE_WLAN_TDLS
15996 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15997 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15998 u32 mask, set;
15999
16000 ENTER();
16001
Anurag Chouhan6d760662016-02-20 16:05:43 +053016002 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016003 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016004 return -EINVAL;
16005 }
16006
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016007 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016008 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016009 return -EINVAL;
16010 }
16011
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016012 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016013 TRACE_CODE_HDD_CFG80211_ADD_STA,
16014 pAdapter->sessionId, params->listen_interval));
16015
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016016 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016017 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016018
16019 mask = params->sta_flags_mask;
16020
16021 set = params->sta_flags_set;
16022
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016023 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016024 MAC_ADDR_ARRAY(mac));
16025
16026 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
16027 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080016028#if defined(CONVERGED_TDLS_ENABLE)
16029 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
16030 dev, mac);
16031#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016032 status =
16033 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080016034#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016035 }
16036 }
16037#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016038 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016039 return status;
16040}
16041
16042/**
16043 * wlan_hdd_cfg80211_add_station() - add station
16044 * @wiphy: Pointer to wiphy
16045 * @mac: Pointer to station mac address
16046 * @pmksa: Pointer to add station parameter
16047 *
16048 * Return: 0 for success, non-zero for failure
16049 */
16050#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
16051static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16052 struct net_device *dev,
16053 const uint8_t *mac,
16054 struct station_parameters *params)
16055#else
16056static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16057 struct net_device *dev, uint8_t *mac,
16058 struct station_parameters *params)
16059#endif
16060{
16061 int ret;
16062
16063 cds_ssr_protect(__func__);
16064 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
16065 cds_ssr_unprotect(__func__);
16066
16067 return ret;
16068}
16069
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016070/**
16071 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
16072 * @wiphy: Pointer to wiphy
16073 * @dev: Pointer to network device
16074 * @pmksa: Pointer to set pmksa parameter
16075 *
16076 * Return: 0 for success, non-zero for failure
16077 */
16078static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
16079 struct net_device *dev,
16080 struct cfg80211_pmksa *pmksa)
16081{
16082 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16083 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16084 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016085 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016086 int status;
16087 tPmkidCacheInfo pmk_id;
16088
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016089 ENTER();
16090
Anurag Chouhan6d760662016-02-20 16:05:43 +053016091 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016092 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016093 return -EINVAL;
16094 }
16095
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016096 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016097 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016098 return -EINVAL;
16099 }
16100
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016101 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016102 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016103 return -EINVAL;
16104 }
16105
16106 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016107 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016108 pmksa->bssid, pmksa->pmkid);
16109 return -EINVAL;
16110 }
16111
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016112 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016113 MAC_ADDR_ARRAY(pmksa->bssid));
16114
16115 status = wlan_hdd_validate_context(pHddCtx);
16116
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016117 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016118 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016119
16120 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16121
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016122 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
16123 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016124
16125 /* Add to the PMKSA ID Cache in CSR */
16126 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
16127 &pmk_id, 1, false);
16128
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016129 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016130 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
16131 pAdapter->sessionId, result));
16132
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016133 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016134 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016135}
16136
16137/**
16138 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
16139 * @wiphy: Pointer to wiphy
16140 * @dev: Pointer to network device
16141 * @pmksa: Pointer to set pmksa parameter
16142 *
16143 * Return: 0 for success, non-zero for failure
16144 */
16145static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
16146 struct net_device *dev,
16147 struct cfg80211_pmksa *pmksa)
16148{
16149 int ret;
16150
16151 cds_ssr_protect(__func__);
16152 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
16153 cds_ssr_unprotect(__func__);
16154
16155 return ret;
16156}
16157
16158/**
16159 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16160 * @wiphy: Pointer to wiphy
16161 * @dev: Pointer to network device
16162 * @pmksa: Pointer to pmksa parameter
16163 *
16164 * Return: 0 for success, non-zero for failure
16165 */
16166static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16167 struct net_device *dev,
16168 struct cfg80211_pmksa *pmksa)
16169{
16170 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16171 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16172 tHalHandle halHandle;
16173 int status = 0;
16174
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016175 ENTER();
16176
Anurag Chouhan6d760662016-02-20 16:05:43 +053016177 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016178 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016179 return -EINVAL;
16180 }
16181
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016182 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16183 hdd_err("invalid session id: %d", pAdapter->sessionId);
16184 return -EINVAL;
16185 }
16186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016187 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016188 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016189 return -EINVAL;
16190 }
16191
16192 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016193 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016194 return -EINVAL;
16195 }
16196
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016197 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016198 MAC_ADDR_ARRAY(pmksa->bssid));
16199
16200 status = wlan_hdd_validate_context(pHddCtx);
16201
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016202 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016203 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016204
16205 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16206
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016207 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016208 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
16209 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016210 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016211 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016212 sme_roam_del_pmkid_from_cache(halHandle,
16213 pAdapter->sessionId, pmksa->bssid,
16214 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016215 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016216 MAC_ADDR_ARRAY(pmksa->bssid));
16217 status = -EINVAL;
16218 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016219 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016220 return status;
16221}
16222
16223/**
16224 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16225 * @wiphy: Pointer to wiphy
16226 * @dev: Pointer to network device
16227 * @pmksa: Pointer to pmksa parameter
16228 *
16229 * Return: 0 for success, non-zero for failure
16230 */
16231static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16232 struct net_device *dev,
16233 struct cfg80211_pmksa *pmksa)
16234{
16235 int ret;
16236
16237 cds_ssr_protect(__func__);
16238 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
16239 cds_ssr_unprotect(__func__);
16240
16241 return ret;
16242
16243}
16244
16245/**
16246 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16247 * @wiphy: Pointer to wiphy
16248 * @dev: Pointer to network device
16249 *
16250 * Return: 0 for success, non-zero for failure
16251 */
16252static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16253 struct net_device *dev)
16254{
16255 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16256 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16257 tHalHandle halHandle;
16258 int status = 0;
16259
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016260 ENTER();
16261
Anurag Chouhan6d760662016-02-20 16:05:43 +053016262 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016263 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016264 return -EINVAL;
16265 }
16266
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016267 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16268 hdd_err("invalid session id: %d", pAdapter->sessionId);
16269 return -EINVAL;
16270 }
16271
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016272 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273
16274 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16275 status = wlan_hdd_validate_context(pHddCtx);
16276
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016277 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016278 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016279
16280 /* Retrieve halHandle */
16281 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16282
16283 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016284 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016285 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
16286 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016287 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016288 status = -EINVAL;
16289 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016290 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016291 return status;
16292}
16293
16294/**
16295 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16296 * @wiphy: Pointer to wiphy
16297 * @dev: Pointer to network device
16298 *
16299 * Return: 0 for success, non-zero for failure
16300 */
16301static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16302 struct net_device *dev)
16303{
16304 int ret;
16305
16306 cds_ssr_protect(__func__);
16307 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
16308 cds_ssr_unprotect(__func__);
16309
16310 return ret;
16311}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016312
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016313#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016314/**
16315 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16316 * @wiphy: Pointer to wiphy
16317 * @dev: Pointer to network device
16318 * @ftie: Pointer to fast transition ie parameter
16319 *
16320 * Return: 0 for success, non-zero for failure
16321 */
16322static int
16323__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16324 struct net_device *dev,
16325 struct cfg80211_update_ft_ies_params *ftie)
16326{
16327 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16328 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16329 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16330 int status;
16331
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016332 ENTER();
16333
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016334 status = wlan_hdd_validate_context(hdd_ctx);
16335 if (status)
16336 return status;
16337
Anurag Chouhan6d760662016-02-20 16:05:43 +053016338 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016339 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016340 return -EINVAL;
16341 }
16342
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016343 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16344 hdd_err("invalid session id: %d", pAdapter->sessionId);
16345 return -EINVAL;
16346 }
16347
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016348 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016349 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
16350 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
16351 /* Added for debug on reception of Re-assoc Req. */
16352 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016353 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016354 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016355 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016356 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016357 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016358 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016359
16360 /* Pass the received FT IEs to SME */
16361 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
16362 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016363 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016364 return 0;
16365}
16366
16367/**
16368 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16369 * @wiphy: Pointer to wiphy
16370 * @dev: Pointer to network device
16371 * @ftie: Pointer to fast transition ie parameter
16372 *
16373 * Return: 0 for success, non-zero for failure
16374 */
16375static int
16376wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16377 struct net_device *dev,
16378 struct cfg80211_update_ft_ies_params *ftie)
16379{
16380 int ret;
16381
16382 cds_ssr_protect(__func__);
16383 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
16384 cds_ssr_unprotect(__func__);
16385
16386 return ret;
16387}
16388#endif
16389
Mukul Sharma3d36c392017-01-18 18:39:12 +053016390void wlan_hdd_cfg80211_update_replay_counter_callback(
16391 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
16392
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016393{
Mukul Sharma3d36c392017-01-18 18:39:12 +053016394 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
16395 uint8_t temp_replay_counter[8];
16396 int i;
16397 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016398
16399 ENTER();
16400
Mukul Sharma3d36c392017-01-18 18:39:12 +053016401 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016402 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016403 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016404 }
16405
Mukul Sharma3d36c392017-01-18 18:39:12 +053016406 if (!gtk_rsp_param) {
16407 hdd_err("gtk_rsp_param is Null");
16408 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016409 }
16410
Mukul Sharma3d36c392017-01-18 18:39:12 +053016411 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016412 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016413 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016414 }
16415
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016416 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016417 gtk_rsp_param->replay_counter);
16418 /* convert little to big endian since supplicant works on big endian */
16419 p = (uint8_t *)&gtk_rsp_param->replay_counter;
16420 for (i = 0; i < 8; i++)
16421 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016422
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016423 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016424 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080016425 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016426 gtk_rsp_param->bssid.bytes,
16427 temp_replay_counter, GFP_KERNEL);
16428out:
16429 EXIT();
16430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016431}
16432
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016433static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016434int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016435 struct net_device *dev,
16436 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016437{
16438 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016439 int result, i;
16440 struct pmo_gtk_req *gtk_req = NULL;
16441 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16442 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016443 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016444
16445 ENTER();
16446
Anurag Chouhan6d760662016-02-20 16:05:43 +053016447 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016448 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016449 result = -EINVAL;
16450 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016451 }
16452
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016453 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16454 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016455 result = -EINVAL;
16456 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016457 }
16458
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016459 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016460 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16461 pAdapter->sessionId, pAdapter->device_mode));
16462
Mukul Sharma3d36c392017-01-18 18:39:12 +053016463 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016464 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016465 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016466
Mukul Sharma3d36c392017-01-18 18:39:12 +053016467 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16468 if (!gtk_req) {
16469 hdd_err("cannot allocate gtk_req");
16470 result = -ENOMEM;
16471 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016472 }
16473
Mukul Sharma3d36c392017-01-18 18:39:12 +053016474 /* convert big to little endian since driver work on little endian */
16475 buf = (uint8_t *)&gtk_req->replay_counter;
16476 for (i = 0; i < 8; i++)
16477 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016478
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016479 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016480 gtk_req->replay_counter);
16481 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16482 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16483 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16484 if (status != QDF_STATUS_SUCCESS) {
16485 hdd_err("Failed to cache GTK Offload");
16486 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016487 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016488out:
16489 if (gtk_req)
16490 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016491 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016492
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016493 return result;
16494}
16495
16496/**
16497 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16498 * @wiphy: Pointer to wiphy
16499 * @dev: Pointer to network device
16500 * @data: Pointer to rekey data
16501 *
16502 * This function is used to offload GTK rekeying job to the firmware.
16503 *
16504 * Return: 0 for success, non-zero for failure
16505 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016506static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016507int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16508 struct net_device *dev,
16509 struct cfg80211_gtk_rekey_data *data)
16510{
16511 int ret;
16512
16513 cds_ssr_protect(__func__);
16514 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16515 cds_ssr_unprotect(__func__);
16516
16517 return ret;
16518}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016519
16520/**
16521 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16522 * @wiphy: Pointer to wiphy
16523 * @dev: Pointer to network device
16524 * @param: Pointer to access control parameter
16525 *
16526 * Return: 0 for success, non-zero for failure
16527 */
16528static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16529 struct net_device *dev,
16530 const struct cfg80211_acl_data *params)
16531{
16532 int i;
16533 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16534 hdd_hostapd_state_t *pHostapdState;
16535 tsap_Config_t *pConfig;
16536 v_CONTEXT_t p_cds_context = NULL;
16537 hdd_context_t *pHddCtx;
16538 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016539 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016540
16541 ENTER();
16542
Anurag Chouhan6d760662016-02-20 16:05:43 +053016543 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016544 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016545 return -EINVAL;
16546 }
16547
16548 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016549 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016550 return -EINVAL;
16551 }
16552
16553 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16554 status = wlan_hdd_validate_context(pHddCtx);
16555
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016556 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016557 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016558
16559 p_cds_context = pHddCtx->pcds_context;
16560 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16561
16562 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016563 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016564 return -EINVAL;
16565 }
16566
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016567 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016568 params->n_acl_entries);
16569
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016570 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016571 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16572 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016573 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016574 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16575
16576 /* default value */
16577 pConfig->num_accept_mac = 0;
16578 pConfig->num_deny_mac = 0;
16579
16580 /**
16581 * access control policy
16582 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16583 * listed in hostapd.deny file.
16584 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16585 * listed in hostapd.accept file.
16586 */
16587 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16588 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16589 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16590 params->acl_policy) {
16591 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16592 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016593 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016594 params->acl_policy);
16595 return -ENOTSUPP;
16596 }
16597
16598 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16599 pConfig->num_accept_mac = params->n_acl_entries;
16600 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016601 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016602 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016603 MAC_ADDR_ARRAY(
16604 params->mac_addrs[i].addr));
16605
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016606 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016607 params->mac_addrs[i].addr,
16608 sizeof(qcmacaddr));
16609 }
16610 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16611 pConfig->num_deny_mac = params->n_acl_entries;
16612 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016613 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016614 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016615 MAC_ADDR_ARRAY(
16616 params->mac_addrs[i].addr));
16617
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016618 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016619 params->mac_addrs[i].addr,
16620 sizeof(qcmacaddr));
16621 }
16622 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016623 qdf_status = wlansap_set_mac_acl(
16624 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016625 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016626 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016627 return -EINVAL;
16628 }
16629 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016630 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016631 hdd_device_mode_to_string(pAdapter->device_mode),
16632 pAdapter->device_mode);
16633 return -EINVAL;
16634 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016635 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016636 return 0;
16637}
16638
16639/**
16640 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16641 * __wlan_hdd_cfg80211_set_mac_acl
16642 * @wiphy: pointer to wiphy structure
16643 * @dev: pointer to net_device
16644 * @params: pointer to cfg80211_acl_data
16645 *
16646 * Return; 0 on success, error number otherwise
16647 */
16648static int
16649wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16650 struct net_device *dev,
16651 const struct cfg80211_acl_data *params)
16652{
16653 int ret;
16654
16655 cds_ssr_protect(__func__);
16656 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16657 cds_ssr_unprotect(__func__);
16658
16659 return ret;
16660}
16661
16662#ifdef WLAN_NL80211_TESTMODE
16663#ifdef FEATURE_WLAN_LPHB
16664/**
16665 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16666 * @pHddCtx: Pointer to hdd context
16667 * @lphbInd: Pointer to low power heart beat indication parameter
16668 *
16669 * Return: none
16670 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016671static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016672 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016673{
16674 struct sk_buff *skb;
16675
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016676 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016677
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016678 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016679 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016680
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016681 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016682 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016683 return;
16684 }
16685
16686 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016687 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016688 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016689 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016690 return;
16691 }
16692
16693 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016694 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016695 goto nla_put_failure;
16696 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016697 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016698 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016699 goto nla_put_failure;
16700 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016701 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16702 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016703 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016704 goto nla_put_failure;
16705 }
16706 cfg80211_testmode_event(skb, GFP_ATOMIC);
16707 return;
16708
16709nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016710 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016711 kfree_skb(skb);
16712
16713 return;
16714}
16715#endif /* FEATURE_WLAN_LPHB */
16716
16717/**
16718 * __wlan_hdd_cfg80211_testmode() - test mode
16719 * @wiphy: Pointer to wiphy
16720 * @data: Data pointer
16721 * @len: Data length
16722 *
16723 * Return: 0 for success, non-zero for failure
16724 */
16725static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16726 void *data, int len)
16727{
16728 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16729 int err;
16730 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16731
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016732 ENTER();
16733
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016734 err = wlan_hdd_validate_context(pHddCtx);
16735 if (err)
16736 return err;
16737
16738 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16739 len, wlan_hdd_tm_policy);
16740 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016741 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016742 return err;
16743 }
16744
16745 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016746 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016747 return -EINVAL;
16748 }
16749
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016750 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016751 TRACE_CODE_HDD_CFG80211_TESTMODE,
16752 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016753 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16754#ifdef FEATURE_WLAN_LPHB
16755 /* Low Power Heartbeat configuration request */
16756 case WLAN_HDD_TM_CMD_WLAN_HB:
16757 {
16758 int buf_len;
16759 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016760 struct pmo_lphb_req *hb_params = NULL;
16761 struct pmo_lphb_req *hb_params_temp = NULL;
16762 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016763
16764 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016765 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016766 return -EINVAL;
16767 }
16768
16769 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16770 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16771
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016772 hb_params_temp = (struct pmo_lphb_req *) buf;
16773 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16774 && (hb_params_temp->params.lphb_tcp_params.
16775 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016776 return -EINVAL;
16777
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016778 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16779 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016780 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016781 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016782 return -ENOMEM;
16783 }
16784
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016785 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016786 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16787 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016788 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016789 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016790 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016791
16792 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016793 return 0;
16794 }
16795#endif /* FEATURE_WLAN_LPHB */
16796
16797#if defined(QCA_WIFI_FTM)
16798 case WLAN_HDD_TM_CMD_WLAN_FTM:
16799 {
16800 int buf_len;
16801 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016802 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016803 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016804 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016805 return -EINVAL;
16806 }
16807
16808 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16809 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16810
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016811 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016812
16813 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16814
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016815 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016816 err = -EBUSY;
16817 break;
16818 }
16819#endif
16820
16821 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016822 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016823 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16824 return -EOPNOTSUPP;
16825 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016826 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016827 return err;
16828}
16829
16830/**
16831 * wlan_hdd_cfg80211_testmode() - test mode
16832 * @wiphy: Pointer to wiphy
16833 * @dev: Pointer to network device
16834 * @data: Data pointer
16835 * @len: Data length
16836 *
16837 * Return: 0 for success, non-zero for failure
16838 */
16839static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16840#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16841 struct wireless_dev *wdev,
16842#endif
16843 void *data, int len)
16844{
16845 int ret;
16846
16847 cds_ssr_protect(__func__);
16848 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16849 cds_ssr_unprotect(__func__);
16850
16851 return ret;
16852}
16853
16854#if defined(QCA_WIFI_FTM)
16855/**
16856 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16857 * @buf: Pointer to buffer
16858 * @buf_len: Buffer length
16859 *
16860 * Return: none
16861 */
16862void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16863{
16864 struct sk_buff *skb;
16865 hdd_context_t *hdd_ctx;
16866
16867 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016868 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016869 return;
16870 }
16871
Anurag Chouhan6d760662016-02-20 16:05:43 +053016872 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016873 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016874 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016875 return;
16876 }
16877
16878 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16879 buf_len, GFP_KERNEL);
16880 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016881 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016882 return;
16883 }
16884
16885 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16886 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16887 goto nla_put_failure;
16888
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016889 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016890
16891 cfg80211_testmode_event(skb, GFP_KERNEL);
16892 return;
16893
16894nla_put_failure:
16895 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016896 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016897}
16898#endif
16899#endif /* CONFIG_NL80211_TESTMODE */
16900
16901#ifdef QCA_HT_2040_COEX
16902/**
16903 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16904 * @wiphy: Pointer to wiphy
16905 * @dev: Pointer to network device
16906 * @chandef: Pointer to channel definition parameter
16907 *
16908 * Return: 0 for success, non-zero for failure
16909 */
16910static int
16911__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16912 struct net_device *dev,
16913 struct cfg80211_chan_def *chandef)
16914{
16915 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16916 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016917 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016918 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016919 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016920
Anurag Chouhan6d760662016-02-20 16:05:43 +053016921 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016922 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016923 return -EINVAL;
16924 }
16925
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016926 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16927 hdd_err("invalid session id: %d", pAdapter->sessionId);
16928 return -EINVAL;
16929 }
16930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016931 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16932 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016933 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016934 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016935
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016936 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016937 sme_get_config_param(pHddCtx->hHal, &sme_config);
16938 switch (chandef->width) {
16939 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016940 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016941 if (sme_config.csrConfig.channelBondingMode24GHz !=
16942 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16943 sme_config.csrConfig.channelBondingMode24GHz =
16944 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16945 sme_update_config(pHddCtx->hHal, &sme_config);
16946 cbModeChange = true;
16947 }
16948 break;
16949
16950 case NL80211_CHAN_WIDTH_40:
16951 if (sme_config.csrConfig.channelBondingMode24GHz ==
16952 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16953 if (NL80211_CHAN_HT40MINUS ==
16954 cfg80211_get_chandef_type(chandef))
16955 sme_config.csrConfig.channelBondingMode24GHz =
16956 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16957 else
16958 sme_config.csrConfig.channelBondingMode24GHz =
16959 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16960 sme_update_config(pHddCtx->hHal, &sme_config);
16961 cbModeChange = true;
16962 }
16963 break;
16964
16965 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016966 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016967 return -EINVAL;
16968 }
16969
16970 if (!cbModeChange)
16971 return 0;
16972
Krunal Sonib4326f22016-03-10 13:05:51 -080016973 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016974 return 0;
16975
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016976 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016977 sme_config.csrConfig.channelBondingMode24GHz);
16978
16979 /* Change SAP ht2040 mode */
16980 status = hdd_set_sap_ht2040_mode(pAdapter,
16981 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016982 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016983 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016984 return -EINVAL;
16985 }
16986
16987 return 0;
16988}
16989
16990/**
16991 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16992 * @wiphy: Pointer to wiphy
16993 * @dev: Pointer to network device
16994 * @chandef: Pointer to channel definition parameter
16995 *
16996 * Return: 0 for success, non-zero for failure
16997 */
16998static int
16999wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
17000 struct net_device *dev,
17001 struct cfg80211_chan_def *chandef)
17002{
17003 int ret;
17004
17005 cds_ssr_protect(__func__);
17006 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
17007 cds_ssr_unprotect(__func__);
17008
17009 return ret;
17010}
17011#endif
17012
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017013#ifdef CHANNEL_SWITCH_SUPPORTED
17014/**
17015 * __wlan_hdd_cfg80211_channel_switch()- function to switch
17016 * channel in SAP/GO
17017 * @wiphy: wiphy pointer
17018 * @dev: dev pointer.
17019 * @csa_params: Change channel params
17020 *
17021 * This function is called to switch channel in SAP/GO
17022 *
17023 * Return: 0 if success else return non zero
17024 */
17025static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
17026 struct net_device *dev,
17027 struct cfg80211_csa_settings *csa_params)
17028{
17029 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
17030 hdd_context_t *hdd_ctx;
17031 uint8_t channel;
17032 uint16_t freq;
17033 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080017034 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017035
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017036 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017037 csa_params->chandef.chan->center_freq);
17038
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017039 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
17040 hdd_err("invalid session id: %d", adapter->sessionId);
17041 return -EINVAL;
17042 }
17043
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017044 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17045 ret = wlan_hdd_validate_context(hdd_ctx);
17046
17047 if (0 != ret)
17048 return ret;
17049
Krunal Sonib4326f22016-03-10 13:05:51 -080017050 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
17051 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017052 return -ENOTSUPP;
17053
17054 freq = csa_params->chandef.chan->center_freq;
17055 channel = cds_freq_to_chan(freq);
17056
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053017057 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
17058
17059 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017060 return ret;
17061}
17062
17063/**
17064 * wlan_hdd_cfg80211_channel_switch()- function to switch
17065 * channel in SAP/GO
17066 * @wiphy: wiphy pointer
17067 * @dev: dev pointer.
17068 * @csa_params: Change channel params
17069 *
17070 * This function is called to switch channel in SAP/GO
17071 *
17072 * Return: 0 if success else return non zero
17073 */
17074static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
17075 struct net_device *dev,
17076 struct cfg80211_csa_settings *csa_params)
17077{
17078 int ret;
17079
17080 cds_ssr_protect(__func__);
17081 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
17082 cds_ssr_unprotect(__func__);
17083 return ret;
17084}
17085#endif
17086
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017087/**
17088 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
17089 * translation from NL to policy manager type
17090 * @type: Generic connection mode type defined in NL
17091 *
17092 *
17093 * This function provides the type translation
17094 *
17095 * Return: cds_con_mode enum
17096 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017097enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017098 enum nl80211_iftype type)
17099{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017100 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017101 switch (type) {
17102 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017103 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017104 break;
17105 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017106 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017107 break;
17108 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017109 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017110 break;
17111 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017112 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017113 break;
17114 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017115 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017116 break;
17117 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017118 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017119 }
17120 return mode;
17121}
17122
17123/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017124 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17125 * @wiphy: Handle to struct wiphy to get handle to module context.
17126 * @chandef: Contains information about the capture channel to be set.
17127 *
17128 * This interface is called if and only if monitor mode interface alone is
17129 * active.
17130 *
17131 * Return: 0 success or error code on failure.
17132 */
17133static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17134 struct cfg80211_chan_def *chandef)
17135{
17136 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
17137 hdd_adapter_t *adapter;
17138 hdd_station_ctx_t *sta_ctx;
17139 struct hdd_mon_set_ch_info *ch_info;
17140 QDF_STATUS status;
17141 tHalHandle hal_hdl;
17142 struct qdf_mac_addr bssid;
17143 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080017144 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017145 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017146 int ret;
17147 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
17148
17149 ENTER();
17150
17151 ret = wlan_hdd_validate_context(hdd_ctx);
17152 if (ret)
17153 return ret;
17154
17155 hal_hdl = hdd_ctx->hHal;
17156
17157 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
17158 if (!adapter)
17159 return -EIO;
17160
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017161 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017162 adapter->dev->name, chan_num, chandef->chan->center_freq);
17163
17164 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17165 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017166 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
17167 roam_profile.ChannelInfo.numOfChannels = 1;
17168 roam_profile.phyMode = ch_info->phy_mode;
17169 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017170 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017171
17172 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
17173 QDF_MAC_ADDR_SIZE);
17174
17175 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017176 /*
17177 * CDS api expects secondary channel for calculating
17178 * the channel params
17179 */
17180 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017181 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017182 if (chan_num >= 1 && chan_num <= 5)
17183 sec_ch = chan_num + 4;
17184 else if (chan_num >= 6 && chan_num <= 13)
17185 sec_ch = chan_num - 4;
17186 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017187 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
17188 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017189 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
17190 &roam_profile);
17191 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017192 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017193 status);
17194 ret = qdf_status_to_os_return(status);
17195 return ret;
17196 }
17197 EXIT();
17198 return 0;
17199}
17200
17201/**
17202 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17203 * @wiphy: Handle to struct wiphy to get handle to module context.
17204 * @chandef: Contains information about the capture channel to be set.
17205 *
17206 * This interface is called if and only if monitor mode interface alone is
17207 * active.
17208 *
17209 * Return: 0 success or error code on failure.
17210 */
17211static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17212 struct cfg80211_chan_def *chandef)
17213{
17214 int ret;
17215
17216 cds_ssr_protect(__func__);
17217 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
17218 cds_ssr_unprotect(__func__);
17219 return ret;
17220}
17221
17222/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017223 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
17224 * @adapter: pointer to adapter
17225 *
17226 * Wrapper function to clear link layer stats.
17227 * return - void
17228 */
17229void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
17230{
17231 tSirLLStatsClearReq link_layer_stats_clear_req;
17232 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
17233
Mukul Sharma491021c2016-09-29 21:39:19 +053017234 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
17235 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017236 link_layer_stats_clear_req.stopReq = 0;
17237 link_layer_stats_clear_req.reqId = 1;
17238 link_layer_stats_clear_req.staId = adapter->sessionId;
17239 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
17240
17241 return;
17242}
17243
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017244/**
17245 * hdd_process_defer_disconnect() - Handle the deferred disconnect
17246 * @adapter: HDD Adapter
17247 *
17248 * If roaming is in progress and there is a request to
17249 * disconnect the session, then it is deferred. Once
17250 * roaming is complete/aborted, then this routine is
17251 * used to resume the disconnect that was deferred
17252 *
17253 * Return: None
17254 */
17255void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
17256{
17257 switch (adapter->defer_disconnect) {
17258 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
17259 adapter->defer_disconnect = 0;
17260 wlan_hdd_disconnect(adapter,
17261 adapter->cfg80211_disconnect_reason);
17262 break;
17263 case DEFER_DISCONNECT_TRY_DISCONNECT:
17264 wlan_hdd_try_disconnect(adapter);
17265 adapter->defer_disconnect = 0;
17266 break;
17267 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017268 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017269 adapter->defer_disconnect);
17270 break;
17271 }
17272}
17273
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017274#define CNT_DIFF(cur, prev) \
17275 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
17276#define MAX_COUNT 0xffffffff
17277static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
17278 struct scan_chan_info *chan,
17279 struct scan_chan_info *info, uint32_t cmd_flag)
17280{
17281 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
17282 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
17283 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
17284
17285 mutex_lock(&hdd_ctx->chan_info_lock);
17286
17287 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
17288 qdf_mem_zero(chan, sizeof(*chan));
17289
17290 chan->freq = info->freq;
17291 chan->noise_floor = info->noise_floor;
17292 chan->clock_freq = info->clock_freq;
17293 chan->cmd_flag = info->cmd_flag;
17294 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
17295
17296 chan->rx_clear_count =
17297 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
17298
17299 chan->tx_frame_count =
17300 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
17301
17302 mutex_unlock(&hdd_ctx->chan_info_lock);
17303
17304}
17305#undef CNT_DIFF
17306#undef MAX_COUNT
17307
17308/**
17309 * wlan_hdd_chan_info_cb() - channel info callback
17310 * @chan_info: struct scan_chan_info
17311 *
17312 * Store channel info into HDD context
17313 *
17314 * Return: None.
17315 */
17316static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
17317{
17318 hdd_context_t *hdd_ctx;
17319 struct scan_chan_info *chan;
17320 uint8_t idx;
17321
17322 ENTER();
17323
17324 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17325 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
17326 hdd_err("hdd_ctx is invalid");
17327 return;
17328 }
17329
17330 if (!hdd_ctx->chan_info) {
17331 hdd_err("chan_info is NULL");
17332 return;
17333 }
17334
17335 chan = hdd_ctx->chan_info;
17336 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
17337 if (chan[idx].freq == info->freq) {
17338 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
17339 info->cmd_flag);
17340 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
17341 chan[idx].cmd_flag, chan[idx].freq,
17342 chan[idx].noise_floor,
17343 chan[idx].cycle_count, chan[idx].rx_clear_count,
17344 chan[idx].clock_freq, chan[idx].cmd_flag,
17345 chan[idx].tx_frame_count, idx);
17346 if (chan[idx].freq == 0)
17347 break;
17348
17349 }
17350 }
17351
17352 EXIT();
17353}
17354
17355/**
17356 * wlan_hdd_init_chan_info() - init chan info in hdd context
17357 * @hdd_ctx: HDD context pointer
17358 *
17359 * Return: none
17360 */
17361void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
17362{
17363 uint8_t num_2g, num_5g, index = 0;
17364
17365 if (!hdd_ctx->config->fEnableSNRMonitoring) {
17366 hdd_info("SNR monitoring is disabled");
17367 return;
17368 }
17369
17370 hdd_ctx->chan_info =
17371 qdf_mem_malloc(sizeof(struct scan_chan_info)
17372 * QDF_MAX_NUM_CHAN);
17373 if (hdd_ctx->chan_info == NULL) {
17374 hdd_err("Failed to malloc for chan info");
17375 return;
17376 }
17377 mutex_init(&hdd_ctx->chan_info_lock);
17378
17379 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
17380 for (; index < num_2g; index++) {
17381 hdd_ctx->chan_info[index].freq =
17382 hdd_channels_2_4_ghz[index].center_freq;
17383 }
17384
17385 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
17386 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017387 if (WLAN_REG_IS_11P_CH(
17388 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017389 continue;
17390 hdd_ctx->chan_info[index].freq =
17391 hdd_channels_5_ghz[index - num_2g].center_freq;
17392 }
17393 sme_set_chan_info_callback(hdd_ctx->hHal,
17394 &wlan_hdd_chan_info_cb);
17395}
17396
17397/**
17398 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
17399 * @hdd_ctx: hdd context pointer
17400 *
17401 * Return: none
17402 */
17403void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
17404{
17405 struct scan_chan_info *chan;
17406
17407 chan = hdd_ctx->chan_info;
17408 hdd_ctx->chan_info = NULL;
17409 if (chan)
17410 qdf_mem_free(chan);
17411}
17412
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017413/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017414 * struct cfg80211_ops - cfg80211_ops
17415 *
17416 * @add_virtual_intf: Add virtual interface
17417 * @del_virtual_intf: Delete virtual interface
17418 * @change_virtual_intf: Change virtual interface
17419 * @change_station: Change station
17420 * @add_beacon: Add beacon in sap mode
17421 * @del_beacon: Delete beacon in sap mode
17422 * @set_beacon: Set beacon in sap mode
17423 * @start_ap: Start ap
17424 * @change_beacon: Change beacon
17425 * @stop_ap: Stop ap
17426 * @change_bss: Change bss
17427 * @add_key: Add key
17428 * @get_key: Get key
17429 * @del_key: Delete key
17430 * @set_default_key: Set default key
17431 * @set_channel: Set channel
17432 * @scan: Scan
17433 * @connect: Connect
17434 * @disconnect: Disconnect
17435 * @join_ibss = Join ibss
17436 * @leave_ibss = Leave ibss
17437 * @set_wiphy_params = Set wiphy params
17438 * @set_tx_power = Set tx power
17439 * @get_tx_power = get tx power
17440 * @remain_on_channel = Remain on channel
17441 * @cancel_remain_on_channel = Cancel remain on channel
17442 * @mgmt_tx = Tx management frame
17443 * @mgmt_tx_cancel_wait = Cancel management tx wait
17444 * @set_default_mgmt_key = Set default management key
17445 * @set_txq_params = Set tx queue parameters
17446 * @get_station = Get station
17447 * @set_power_mgmt = Set power management
17448 * @del_station = Delete station
17449 * @add_station = Add station
17450 * @set_pmksa = Set pmksa
17451 * @del_pmksa = Delete pmksa
17452 * @flush_pmksa = Flush pmksa
17453 * @update_ft_ies = Update FT IEs
17454 * @tdls_mgmt = Tdls management
17455 * @tdls_oper = Tdls operation
17456 * @set_rekey_data = Set rekey data
17457 * @sched_scan_start = Scheduled scan start
17458 * @sched_scan_stop = Scheduled scan stop
17459 * @resume = Resume wlan
17460 * @suspend = Suspend wlan
17461 * @set_mac_acl = Set mac acl
17462 * @testmode_cmd = Test mode command
17463 * @set_ap_chanwidth = Set AP channel bandwidth
17464 * @dump_survey = Dump survey
17465 * @key_mgmt_set_pmk = Set pmk key management
17466 */
17467static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17468 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17469 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17470 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17471 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017472 .start_ap = wlan_hdd_cfg80211_start_ap,
17473 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17474 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017475 .change_bss = wlan_hdd_cfg80211_change_bss,
17476 .add_key = wlan_hdd_cfg80211_add_key,
17477 .get_key = wlan_hdd_cfg80211_get_key,
17478 .del_key = wlan_hdd_cfg80211_del_key,
17479 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17480 .scan = wlan_hdd_cfg80211_scan,
17481 .connect = wlan_hdd_cfg80211_connect,
17482 .disconnect = wlan_hdd_cfg80211_disconnect,
17483 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17484 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17485 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17486 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17487 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17488 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17489 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17490 .mgmt_tx = wlan_hdd_mgmt_tx,
17491 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17492 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17493 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017494 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017495 .get_station = wlan_hdd_cfg80211_get_station,
17496 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17497 .del_station = wlan_hdd_cfg80211_del_station,
17498 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017499 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17500 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17501 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017502#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017503 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17504#endif
17505#ifdef FEATURE_WLAN_TDLS
17506 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17507 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17508#endif
17509#ifdef WLAN_FEATURE_GTK_OFFLOAD
17510 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17511#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17512#ifdef FEATURE_WLAN_SCAN_PNO
17513 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17514 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17515#endif /*FEATURE_WLAN_SCAN_PNO */
17516 .resume = wlan_hdd_cfg80211_resume_wlan,
17517 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17518 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17519#ifdef WLAN_NL80211_TESTMODE
17520 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17521#endif
17522#ifdef QCA_HT_2040_COEX
17523 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17524#endif
17525 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017526#ifdef CHANNEL_SWITCH_SUPPORTED
17527 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17528#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017529 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017530#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17531 defined(CFG80211_ABORT_SCAN)
17532 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17533#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017534};