blob: b5fe3508d4256dbc1adc755dae5f1701e3275e8d [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
805/* vendor specific events */
806static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
812 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813
814#ifdef WLAN_FEATURE_NAN
815 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
816 .vendor_id =
817 QCA_NL80211_VENDOR_ID,
818 .subcmd =
819 QCA_NL80211_VENDOR_SUBCMD_NAN
820 },
821#endif
822
823#ifdef WLAN_FEATURE_STATS_EXT
824 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
825 .vendor_id =
826 QCA_NL80211_VENDOR_ID,
827 .subcmd =
828 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
829 },
830#endif /* WLAN_FEATURE_STATS_EXT */
831#ifdef FEATURE_WLAN_EXTSCAN
832 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
833 .vendor_id =
834 QCA_NL80211_VENDOR_ID,
835 .subcmd =
836 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
837 },
838 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
839 .vendor_id =
840 QCA_NL80211_VENDOR_ID,
841 .subcmd =
842 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
843 },
844 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
845 .
846 vendor_id
847 =
848 QCA_NL80211_VENDOR_ID,
849 .subcmd =
850 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
851 },
852 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
853 .
854 vendor_id
855 =
856 QCA_NL80211_VENDOR_ID,
857 .
858 subcmd =
859 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
860 },
861 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
862 .
863 vendor_id
864 =
865 QCA_NL80211_VENDOR_ID,
866 .
867 subcmd
868 =
869 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
870 },
871 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
872 .
873 vendor_id
874 =
875 QCA_NL80211_VENDOR_ID,
876 .subcmd =
877 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
878 },
879 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
880 .vendor_id =
881 QCA_NL80211_VENDOR_ID,
882 .subcmd =
883 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
884 },
885 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
886 .
887 vendor_id
888 =
889 QCA_NL80211_VENDOR_ID,
890 .subcmd =
891 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
892 },
893 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
894 .
895 vendor_id
896 =
897 QCA_NL80211_VENDOR_ID,
898 .subcmd =
899 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
900 },
901 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
902 .
903 vendor_id
904 =
905 QCA_NL80211_VENDOR_ID,
906 .
907 subcmd
908 =
909 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
910 },
911 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
912 .
913 vendor_id
914 =
915 QCA_NL80211_VENDOR_ID,
916 .
917 subcmd =
918 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
919 },
920 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
921 .
922 vendor_id
923 =
924 QCA_NL80211_VENDOR_ID,
925 .
926 subcmd
927 =
928 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
929 },
930 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
931 .
932 vendor_id
933 =
934 QCA_NL80211_VENDOR_ID,
935 .
936 subcmd
937 =
938 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
939 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800940#endif /* FEATURE_WLAN_EXTSCAN */
941
942#ifdef WLAN_FEATURE_LINK_LAYER_STATS
943 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
944 .vendor_id =
945 QCA_NL80211_VENDOR_ID,
946 .subcmd =
947 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
948 },
949 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
950 .vendor_id =
951 QCA_NL80211_VENDOR_ID,
952 .subcmd =
953 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
954 },
955 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
956 .vendor_id =
957 QCA_NL80211_VENDOR_ID,
958 .subcmd =
959 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
960 },
961 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
962 .vendor_id =
963 QCA_NL80211_VENDOR_ID,
964 .subcmd =
965 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
966 },
967 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
968 .vendor_id =
969 QCA_NL80211_VENDOR_ID,
970 .subcmd =
971 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
972 },
973 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
974 .vendor_id =
975 QCA_NL80211_VENDOR_ID,
976 .subcmd =
977 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
978 },
Zhang Qianca38fb12016-12-23 11:10:48 +0800979 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
980 .vendor_id =
981 QCA_NL80211_VENDOR_ID,
982 .subcmd =
983 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
984 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800985#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
986 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
987 .vendor_id =
988 QCA_NL80211_VENDOR_ID,
989 .subcmd =
990 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
991 },
992 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
993 .vendor_id = QCA_NL80211_VENDOR_ID,
994 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
995 },
996#ifdef WLAN_FEATURE_ROAM_OFFLOAD
997 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
998 .vendor_id =
999 QCA_NL80211_VENDOR_ID,
1000 .subcmd =
1001 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1002 },
1003#endif
1004 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1005 .vendor_id =
1006 QCA_NL80211_VENDOR_ID,
1007 .subcmd =
1008 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1009 },
1010 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1011 .vendor_id =
1012 QCA_NL80211_VENDOR_ID,
1013 .subcmd =
1014 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1015 },
1016 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1017 .vendor_id =
1018 QCA_NL80211_VENDOR_ID,
1019 .subcmd =
1020 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1021 },
1022 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1023 .vendor_id =
1024 QCA_NL80211_VENDOR_ID,
1025 .subcmd =
1026 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1027 },
1028 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1029 .vendor_id =
1030 QCA_NL80211_VENDOR_ID,
1031 .subcmd =
1032 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1033 },
1034#ifdef FEATURE_WLAN_EXTSCAN
1035 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1036 .vendor_id = QCA_NL80211_VENDOR_ID,
1037 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1038 },
1039 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1040 .vendor_id = QCA_NL80211_VENDOR_ID,
1041 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1042 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001043 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1046 },
1047#endif /* FEATURE_WLAN_EXTSCAN */
1048 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1051 },
1052#ifdef WLAN_FEATURE_MEMDUMP
1053 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1056 },
1057#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001058#ifdef WLAN_FEATURE_TSF
1059 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1060 .vendor_id = QCA_NL80211_VENDOR_ID,
1061 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1062 },
1063#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001064 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1067 },
1068 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1069 .vendor_id = QCA_NL80211_VENDOR_ID,
1070 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1071 },
1072 /* OCB events */
1073 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1076 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001077#ifdef FEATURE_LFR_SUBNET_DETECTION
1078 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1081 },
1082#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001083
1084#ifdef WLAN_FEATURE_NAN_DATAPATH
1085 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1086 .vendor_id = QCA_NL80211_VENDOR_ID,
1087 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1088 },
1089#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001090
1091 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1092 .vendor_id = QCA_NL80211_VENDOR_ID,
1093 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1094 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301095 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1096 .vendor_id = QCA_NL80211_VENDOR_ID,
1097 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1098 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301099 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1100 .vendor_id = QCA_NL80211_VENDOR_ID,
1101 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1102 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001103#ifdef WLAN_UMAC_CONVERGENCE
1104 COMMON_VENDOR_EVENTS
1105#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001106};
1107
1108/**
1109 * __is_driver_dfs_capable() - get driver DFS capability
1110 * @wiphy: pointer to wireless wiphy structure.
1111 * @wdev: pointer to wireless_dev structure.
1112 * @data: Pointer to the data to be passed via vendor interface
1113 * @data_len:Length of the data to be passed
1114 *
1115 * This function is called by userspace to indicate whether or not
1116 * the driver supports DFS offload.
1117 *
1118 * Return: 0 on success, negative errno on failure
1119 */
1120static int __is_driver_dfs_capable(struct wiphy *wiphy,
1121 struct wireless_dev *wdev,
1122 const void *data,
1123 int data_len)
1124{
1125 u32 dfs_capability = 0;
1126 struct sk_buff *temp_skbuff;
1127 int ret_val;
1128 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1129
Jeff Johnson1f61b612016-02-12 16:28:33 -08001130 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131
1132 ret_val = wlan_hdd_validate_context(hdd_ctx);
1133 if (ret_val)
1134 return ret_val;
1135
Anurag Chouhan6d760662016-02-20 16:05:43 +05301136 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 hdd_err("Command not allowed in FTM mode");
1138 return -EPERM;
1139 }
1140
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142
1143 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1144 NLMSG_HDRLEN);
1145
1146 if (temp_skbuff != NULL) {
1147 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1148 dfs_capability);
1149 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001150 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 kfree_skb(temp_skbuff);
1152
1153 return ret_val;
1154 }
1155
1156 return cfg80211_vendor_cmd_reply(temp_skbuff);
1157 }
1158
Jeff Johnson020db452016-06-29 14:37:26 -07001159 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160 return -ENOMEM;
1161}
1162
1163/**
1164 * is_driver_dfs_capable() - get driver DFS capability
1165 * @wiphy: pointer to wireless wiphy structure.
1166 * @wdev: pointer to wireless_dev structure.
1167 * @data: Pointer to the data to be passed via vendor interface
1168 * @data_len:Length of the data to be passed
1169 *
1170 * This function is called by userspace to indicate whether or not
1171 * the driver supports DFS offload. This is an SSR-protected
1172 * wrapper function.
1173 *
1174 * Return: 0 on success, negative errno on failure
1175 */
1176static int is_driver_dfs_capable(struct wiphy *wiphy,
1177 struct wireless_dev *wdev,
1178 const void *data,
1179 int data_len)
1180{
1181 int ret;
1182
1183 cds_ssr_protect(__func__);
1184 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1185 cds_ssr_unprotect(__func__);
1186
1187 return ret;
1188}
1189
1190/**
1191 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1192 *
1193 * @adapter: SAP adapter pointer
1194 *
1195 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1196 * radio. So in case of DFS MCC scenario override current SAP given config
1197 * to follow concurrent SAP DFS config
1198 *
1199 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1200 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001201int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1202{
1203 hdd_adapter_t *con_sap_adapter;
1204 tsap_Config_t *sap_config, *con_sap_config;
1205 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001206 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001208 if (!hdd_ctx) {
1209 hdd_err("hdd context is NULL");
1210 return 0;
1211 }
1212
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213 /*
1214 * Check if AP+AP case, once primary AP chooses a DFS
1215 * channel secondary AP should always follow primary APs channel
1216 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001217 if (!policy_mgr_concurrent_beaconing_sessions_running(
1218 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 return 0;
1220
1221 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1222 if (!con_sap_adapter)
1223 return 0;
1224
1225 sap_config = &adapter->sessionCtx.ap.sapConfig;
1226 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1227 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1228
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001229 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 return 0;
1231
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001232 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001234 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001235 sap_config->channel = con_ch;
1236
1237 if (con_sap_config->acs_cfg.acs_mode == true) {
1238 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1239 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001240 hdd_err("Primary AP channel config error");
1241 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 con_ch, con_sap_config->acs_cfg.pri_ch,
1243 con_sap_config->acs_cfg.ht_sec_ch);
1244 return -EINVAL;
1245 }
1246 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1247 * MCC restriction. So free ch list allocated in do_acs
1248 * func for Sec AP and realloc for Pri AP ch list size
1249 */
1250 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301253 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001254 &con_sap_config->acs_cfg,
1255 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301256 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 sizeof(uint8_t) *
1258 con_sap_config->acs_cfg.ch_list_count);
1259 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001260 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 return -ENOMEM;
1262 }
1263
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301264 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265 con_sap_config->acs_cfg.ch_list,
1266 con_sap_config->acs_cfg.ch_list_count);
1267
1268 } else {
1269 sap_config->acs_cfg.pri_ch = con_ch;
1270 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1271 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1272 }
1273
1274 return con_ch;
1275}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001276
1277/**
1278 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1279 * @sap_cfg: pointer to SAP config struct
1280 *
1281 * This function sets the default ACS start and end channel for the given band
1282 * and also parses the given ACS channel list.
1283 *
1284 * Return: None
1285 */
1286
1287static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1288 bool vht_enabled)
1289{
1290 int i;
1291 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001293 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1294 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1296 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001297 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1298 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001301 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1302 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1304 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001305 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1306 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001307 }
1308
1309 if (ht_enabled)
1310 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1311
1312 if (vht_enabled)
1313 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1314
1315
1316 /* Parse ACS Chan list from hostapd */
1317 if (!sap_cfg->acs_cfg.ch_list)
1318 return;
1319
1320 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1321 sap_cfg->acs_cfg.end_ch =
1322 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1323 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301324 /* avoid channel as start channel */
1325 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1326 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1328 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1329 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1330 }
1331}
1332
1333
1334static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1335
1336/**
1337 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1338 * @adapter: pointer to SAP adapter struct
1339 *
1340 * This function starts the ACS procedure if there are no
1341 * constraints like MBSSID DFS restrictions.
1342 *
1343 * Return: Status of ACS Start procedure
1344 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301345int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001346{
1347
1348 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1349 tsap_Config_t *sap_config;
1350 tpWLAN_SAPEventCB acs_event_callback;
1351 int status;
1352
1353 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301354 if (hdd_ctx->acs_policy.acs_channel)
1355 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1356 else
1357 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358
1359 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001360 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001362
1363 if (status > 0) {
1364 /*notify hostapd about channel override */
1365 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1366 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1367 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 }
Jeff Johnson68755312017-02-10 11:46:55 -08001369
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1371 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001372 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 return -EINVAL;
1374 }
1375
1376 acs_event_callback = hdd_hostapd_sap_event_cb;
1377
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301378 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301379 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301380 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 acs_event_callback, sap_config, adapter->dev);
1384
1385
1386 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001387 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 return -EINVAL;
1389 }
bings394afdd2017-01-09 11:22:38 +08001390 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1391 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1393
1394 return 0;
1395}
1396
1397/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301398 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1399 * @ap_adapter: AP adapter
1400 * @nol: Non-occupancy list
1401 * @nol_len: Length of NOL
1402 *
1403 * Get the NOL for SAP
1404 *
1405 * Return: Zero on success, non-zero on failure
1406 */
1407static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1408 uint32_t *nol_len)
1409{
1410 QDF_STATUS ret;
1411
1412 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1413 nol, nol_len);
1414 if (QDF_IS_STATUS_ERROR(ret))
1415 return -EINVAL;
1416
1417 return 0;
1418}
1419
1420/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301421 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1422 * @hdd_ctx: hdd context
1423 * @acs_chan_params: external acs channel params
1424 * @sap_config: SAP config
1425 *
1426 * This API provides unsorted pcl list.
1427 * this list is a subset of the valid channel list given by hostapd.
1428 * if channel is not present in pcl, weightage will be given as zero
1429 *
1430 * Return: Zero on success, non-zero on failure
1431 */
1432static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1433 struct hdd_vendor_acs_chan_params *acs_chan_params,
1434 tsap_Config_t *sap_config)
1435{
1436 int i, j;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301437 bool found;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301438
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301439 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1440 hdd_ctx->config->external_acs_policy) {
1441 /*
1442 * In preferred channels mandatory case, PCL shall
1443 * contain only the preferred channels from the
1444 * application. If those channels are not present
1445 * in the driver PCL, then set the weight to zero
1446 */
1447 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1448 acs_chan_params->vendor_pcl_list[i] =
1449 sap_config->acs_cfg.ch_list[i];
1450 acs_chan_params->vendor_weight_list[i] = 0;
1451 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1452 if (sap_config->acs_cfg.ch_list[i] ==
Kapil Gupta8878ad92017-02-13 11:56:04 +05301453 sap_config->acs_cfg.pcl_channels[j]) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301454 acs_chan_params->vendor_weight_list[i] =
1455 sap_config->
1456 acs_cfg.pcl_channels_weight_list[j];
1457 break;
1458 }
1459 }
1460 }
1461 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
1462 } else {
1463 /*
1464 * In preferred channels not mandatory case update the
1465 * PCL weight to zero for those channels which are not
1466 * present in the application's preferred channel list for
1467 * ACS
1468 */
1469 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++) {
1470 found = false;
1471 for (j = 0; j < sap_config->acs_cfg.ch_list_count;
1472 j++) {
1473 if (sap_config->acs_cfg.pcl_channels[i] ==
1474 sap_config->acs_cfg.ch_list[j]) {
1475 acs_chan_params->vendor_pcl_list[i] =
1476 sap_config->
1477 acs_cfg.pcl_channels[i];
1478 acs_chan_params->
1479 vendor_weight_list[i] =
1480 sap_config->acs_cfg.
1481 pcl_channels_weight_list[i];
1482 found = true;
1483 break;
1484 }
1485 }
1486 if (!found) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05301487 acs_chan_params->vendor_pcl_list[i] =
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301488 sap_config->acs_cfg.pcl_channels[i];
Kapil Gupta8878ad92017-02-13 11:56:04 +05301489 acs_chan_params->vendor_weight_list[i] = 0;
1490 }
1491 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301492
1493 acs_chan_params->pcl_count = sap_config->acs_cfg.pcl_ch_count;
1494
1495 if (hdd_ctx->unsafe_channel_count == 0)
1496 return;
1497 /* Update unsafe channel weight as zero */
1498 for (i = 0; i < acs_chan_params->pcl_count; i++) {
1499 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1500 if (acs_chan_params->vendor_pcl_list[i] ==
Kapil Gupta8878ad92017-02-13 11:56:04 +05301501 hdd_ctx->unsafe_channel_list[j]) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301502 acs_chan_params->
1503 vendor_weight_list[i] = 0;
1504 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301505 }
1506 }
1507 }
1508}
1509
1510/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301511 * hdd_update_reg_chan_info : This API contructs channel info
1512 * for all the given channel
1513 * @adapter: pointer to SAP adapter struct
1514 * @channel_count: channel count
1515 * @channel_list: channel list
1516 *
1517 * Return: Status of of channel information updation
1518 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301519static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301520 uint32_t channel_count,
1521 uint8_t *channel_list)
1522{
1523 int i;
1524 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001525 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301526 uint8_t bw_offset = 0, chan = 0;
1527 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1528 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1529
1530 /* memory allocation */
1531 sap_config->channel_info = qdf_mem_malloc(
1532 sizeof(struct hdd_channel_info) *
1533 channel_count);
1534 if (!sap_config->channel_info) {
1535 hdd_err("memory allocation failed");
1536 return -ENOMEM;
1537
1538 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301539 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301540 for (i = 0; i < channel_count; i++) {
1541 icv = &sap_config->channel_info[i];
1542 chan = channel_list[i];
1543
1544 if (chan == 0)
1545 continue;
1546
1547 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1548 bw_offset = 1 << BW_40_OFFSET_BIT;
1549 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1550 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001551 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301552 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001553 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1554 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301555
1556 /* filling demo values */
1557 icv->max_radio_power = HDD_MAX_TX_POWER;
1558 icv->min_radio_power = HDD_MIN_TX_POWER;
1559 /* not supported in current driver */
1560 icv->max_antenna_gain = 0;
1561
1562 icv->reg_class_id = wlan_hdd_find_opclass(
1563 WLAN_HDD_GET_HAL_CTX(adapter),
1564 chan, bw_offset);
1565
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001566 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301567 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001568 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1569 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301570 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1571 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1572 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001573
Kapil Gupta086c6202016-12-11 18:17:06 +05301574 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001575 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301576 sap_config->acs_cfg.ch_width,
1577 sap_config->acs_cfg.is_ht_enabled,
1578 sap_config->acs_cfg.is_vht_enabled,
1579 hdd_ctx->config->enable_sub_20_channel_width);
1580
1581 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1582 icv->freq, icv->flags,
1583 icv->flagext, icv->ieee_chan_number,
1584 icv->max_reg_power, icv->max_radio_power,
1585 icv->min_radio_power, icv->reg_class_id,
1586 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1587 icv->vht_center_freq_seg1);
1588 }
1589 return 0;
1590}
1591
1592/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1593#define CHAN_INFO_ATTR_FLAGS \
1594 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1595#define CHAN_INFO_ATTR_FLAG_EXT \
1596 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1597#define CHAN_INFO_ATTR_FREQ \
1598 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1599#define CHAN_INFO_ATTR_MAX_REG_POWER \
1600 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1601#define CHAN_INFO_ATTR_MAX_POWER \
1602 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1603#define CHAN_INFO_ATTR_MIN_POWER \
1604 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1605#define CHAN_INFO_ATTR_REG_CLASS_ID \
1606 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1607#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1608 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1609#define CHAN_INFO_ATTR_VHT_SEG_0 \
1610 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1611#define CHAN_INFO_ATTR_VHT_SEG_1 \
1612 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1613
1614/**
1615 * hdd_cfg80211_update_channel_info() - add channel info attributes
1616 * @skb: pointer to sk buff
1617 * @hdd_ctx: pointer to hdd station context
1618 * @idx: attribute index
1619 *
1620 * Return: Success(0) or reason code for failure
1621 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301622static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301623hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1624 tsap_Config_t *sap_config, int idx)
1625{
1626 struct nlattr *nla_attr, *channel;
1627 struct hdd_channel_info *icv;
1628 int i;
1629
1630 nla_attr = nla_nest_start(skb, idx);
1631 if (!nla_attr)
1632 goto fail;
1633
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301634 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301635 channel = nla_nest_start(skb, i);
1636 if (!channel)
1637 goto fail;
1638
1639 icv = &sap_config->channel_info[i];
1640 if (!icv) {
1641 hdd_err("channel info not found");
1642 goto fail;
1643 }
1644 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1645 icv->freq) ||
1646 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1647 icv->flags) ||
1648 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1649 icv->flagext) ||
1650 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1651 icv->max_reg_power) ||
1652 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1653 icv->max_radio_power) ||
1654 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1655 icv->min_radio_power) ||
1656 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1657 icv->reg_class_id) ||
1658 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1659 icv->max_antenna_gain) ||
1660 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1661 icv->vht_center_freq_seg0) ||
1662 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1663 icv->vht_center_freq_seg1)) {
1664 hdd_err("put fail");
1665 goto fail;
1666 }
1667 nla_nest_end(skb, channel);
1668 }
1669 nla_nest_end(skb, nla_attr);
1670 return 0;
1671fail:
1672 hdd_err("nl channel update failed");
1673 return -EINVAL;
1674}
1675#undef CHAN_INFO_ATTR_FLAGS
1676#undef CHAN_INFO_ATTR_FLAG_EXT
1677#undef CHAN_INFO_ATTR_FREQ
1678#undef CHAN_INFO_ATTR_MAX_REG_POWER
1679#undef CHAN_INFO_ATTR_MAX_POWER
1680#undef CHAN_INFO_ATTR_MIN_POWER
1681#undef CHAN_INFO_ATTR_REG_CLASS_ID
1682#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1683#undef CHAN_INFO_ATTR_VHT_SEG_0
1684#undef CHAN_INFO_ATTR_VHT_SEG_1
1685
1686/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301687 * hdd_cfg80211_update_pcl() - add pcl info attributes
1688 * @skb: pointer to sk buff
1689 * @hdd_ctx: pointer to hdd station context
1690 * @idx: attribute index
1691 * @vendor_pcl_list: PCL list
1692 * @vendor_weight_list: PCL weights
1693 *
1694 * Return: Success(0) or reason code for failure
1695 */
1696static int32_t
1697hdd_cfg80211_update_pcl(struct sk_buff *skb,
1698 uint8_t ch_list_count, int idx,
1699 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1700{
1701 struct nlattr *nla_attr, *channel;
1702 int i;
1703
1704 nla_attr = nla_nest_start(skb, idx);
1705
1706 if (!nla_attr)
1707 goto fail;
1708
1709 for (i = 0; i < ch_list_count; i++) {
1710 channel = nla_nest_start(skb, i);
1711 if (!channel)
1712 goto fail;
1713 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1714 vendor_pcl_list[i]) ||
1715 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1716 vendor_weight_list[i])) {
1717 hdd_err("put fail");
1718 goto fail;
1719 }
1720 nla_nest_end(skb, channel);
1721 }
1722 nla_nest_end(skb, nla_attr);
1723
1724 return 0;
1725fail:
1726 hdd_err("updating pcl list failed");
1727 return -EINVAL;
1728}
1729
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301730static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
1731 tsap_Config_t *sap_config,
1732 eCsrBand *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301733{
1734 /* Get scan band */
1735 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1736 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1737 *band = eCSR_BAND_24;
1738 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1739 *band = eCSR_BAND_5G;
1740 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1741 *band = eCSR_BAND_ALL;
1742 }
1743 /* Auto is not supported currently */
1744 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1745 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301746 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
1747 hdd_ctx->config->external_acs_freq_band)
1748 *band = eCSR_BAND_24;
1749 else
1750 *band = eCSR_BAND_5G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301751 }
1752}
1753
1754void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1755 uint8_t reason)
1756{
1757 struct sk_buff *skb;
1758 tsap_Config_t *sap_config;
1759 uint32_t channel_count = 0, status;
1760 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1761 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1762 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1763 struct hdd_vendor_acs_chan_params acs_chan_params;
1764 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1765 eCsrBand band = eCSR_BAND_24;
1766 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301767 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
1768 uint32_t i;
1769
Kapil Gupta8878ad92017-02-13 11:56:04 +05301770
1771 if (!hdd_ctx) {
1772 hdd_err("HDD context is NULL");
1773 return;
1774 }
1775
1776 ENTER();
1777 sap_config = &adapter->sessionCtx.ap.sapConfig;
1778
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301779 hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301780 /* Get valid channels for SAP */
1781 wlan_hdd_sap_get_valid_channellist(adapter,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301782 &channel_count,
1783 channel_list,
1784 band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301785
1786 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301787 /* Get phymode */
1788 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1789
1790 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1791 &(adapter->wdev),
1792 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1793 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1794 GFP_KERNEL);
1795
1796 if (!skb) {
1797 hdd_err("cfg80211_vendor_event_alloc failed");
1798 return;
1799 }
1800 /*
1801 * Application expects pcl to be a subset of channel list
1802 * Remove all channels which are not in channel list from pcl
1803 * and add weight as zero
1804 */
1805 acs_chan_params.channel_count = channel_count;
1806 acs_chan_params.channel_list = channel_list;
1807 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1808 acs_chan_params.vendor_weight_list = vendor_weight_list;
1809
1810 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1811 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301812
1813 if (acs_chan_params.channel_count) {
1814 hdd_debug("ACS channel list: len: %d",
1815 acs_chan_params.channel_count);
1816 for (i = 0; i < acs_chan_params.channel_count; i++)
1817 hdd_debug("%d ", acs_chan_params.channel_list[i]);
1818 }
1819
1820 if (acs_chan_params.pcl_count) {
1821 hdd_debug("ACS PCL list: len: %d",
1822 acs_chan_params.pcl_count);
1823 for (i = 0; i < acs_chan_params.pcl_count; i++)
1824 hdd_debug("channel:%d, weight:%d ",
1825 acs_chan_params.
1826 vendor_pcl_list[i],
1827 acs_chan_params.
1828 vendor_weight_list[i]);
1829 }
1830
1831 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1832 hdd_ctx->config->external_acs_policy) {
1833 acs_policy =
1834 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
1835 } else {
1836 acs_policy =
1837 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
1838 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301839 /* Update values in NL buffer */
1840 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1841 reason) ||
1842 nla_put_u8(skb,
1843 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1844 false) ||
1845 nla_put_u8(skb,
1846 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1847 true) ||
1848 nla_put_u8(skb,
1849 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1850 true) ||
1851 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1852 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05301853 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1854 band) ||
1855 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1856 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05301857 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301858 channel_count, channel_list)) {
1859 hdd_err("nla put fail");
1860 goto fail;
1861 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301862 status =
1863 hdd_cfg80211_update_pcl(skb,
1864 acs_chan_params.
1865 pcl_count,
1866 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1867 vendor_pcl_list,
1868 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301869
1870 if (status != 0)
1871 goto fail;
1872
1873 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1874 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1875
1876 if (status != 0)
1877 goto fail;
1878
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301879 status = nla_put_u32(skb,
1880 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
1881 acs_policy);
1882
1883 if (status != 0)
1884 goto fail;
1885
Kapil Gupta8878ad92017-02-13 11:56:04 +05301886 cfg80211_vendor_event(skb, GFP_KERNEL);
1887 return;
1888fail:
1889 if (skb)
1890 kfree_skb(skb);
1891}
1892
1893static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1894{
1895 struct hdd_external_acs_timer_context *timer_context;
1896
1897 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1898 return 0;
1899
1900 hdd_notice("Starting vendor app based ACS");
1901 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1902 timer_context->adapter = adapter;
1903
1904 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1905 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1906 QDF_TIMER_TYPE_SW,
1907 hdd_acs_response_timeout_handler, timer_context);
1908 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1909 return 0;
1910}
1911
1912/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1914 * @wiphy: Linux wiphy struct pointer
1915 * @wdev: Linux wireless device struct pointer
1916 * @data: ACS information from hostapd
1917 * @data_len: ACS information length
1918 *
1919 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1920 * and starts ACS procedure.
1921 *
1922 * Return: ACS procedure start status
1923 */
1924
1925static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1926 struct wireless_dev *wdev,
1927 const void *data, int data_len)
1928{
1929 struct net_device *ndev = wdev->netdev;
1930 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1931 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1932 tsap_Config_t *sap_config;
1933 struct sk_buff *temp_skbuff;
1934 int status = -EINVAL, i = 0;
1935 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1936 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301937 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001938
1939 /* ***Note*** Donot set SME config related to ACS operation here because
1940 * ACS operation is not synchronouse and ACS for Second AP may come when
1941 * ACS operation for first AP is going on. So only do_acs is split to
1942 * seperate start_acs routine. Also SME-PMAC struct that is used to
1943 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1944 * config shall be set only from start_acs.
1945 */
1946
1947 /* nla_policy Policy template. Policy not applied as some attributes are
1948 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1949 *
1950 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1951 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1952 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1953 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1954 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1955 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1956 */
1957
Jeff Johnson1f61b612016-02-12 16:28:33 -08001958 ENTER_DEV(ndev);
1959
Anurag Chouhan6d760662016-02-20 16:05:43 +05301960 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001961 hdd_err("Command not allowed in FTM mode");
1962 return -EPERM;
1963 }
1964
Kapil Gupta8878ad92017-02-13 11:56:04 +05301965 if (hdd_ctx->config->force_sap_acs &&
1966 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001967 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 return -EPERM;
1969 }
1970
1971 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301972 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301974
Naveen Rawat64e477e2016-05-20 10:34:56 -07001975 if (cds_is_sub_20_mhz_enabled()) {
1976 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1977 status = -EINVAL;
1978 goto out;
1979 }
1980
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301982 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983
1984 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1985 NULL);
1986 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001987 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 goto out;
1989 }
1990
1991 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001992 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993 goto out;
1994 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301995 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1996 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997
1998 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1999 ht_enabled =
2000 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2001 else
2002 ht_enabled = 0;
2003
2004 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2005 ht40_enabled =
2006 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2007 else
2008 ht40_enabled = 0;
2009
2010 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2011 vht_enabled =
2012 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2013 else
2014 vht_enabled = 0;
2015
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302016 if (hdd_ctx->config->sap_force_11n_for_11ac) {
2017 vht_enabled = 0;
2018 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
2019 }
2020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2022 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2023 } else {
2024 if (ht_enabled && ht40_enabled)
2025 ch_width = 40;
2026 else
2027 ch_width = 20;
2028 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302029
2030 /* this may be possible, when sap_force_11n_for_11ac is set */
2031 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2032 if (ht_enabled && ht40_enabled)
2033 ch_width = 40;
2034 else
2035 ch_width = 20;
2036 }
2037
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038 if (ch_width == 80)
2039 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2040 else if (ch_width == 40)
2041 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2042 else
2043 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2044
2045 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2046 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2047 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2048 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2049 * since it contains the frequency values of the channels in
2050 * the channel list.
2051 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2052 * is present
2053 */
2054 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2055 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2056 sap_config->acs_cfg.ch_list_count = nla_len(
2057 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2058 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302059 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002060 sizeof(uint8_t) *
2061 sap_config->acs_cfg.ch_list_count);
2062 if (sap_config->acs_cfg.ch_list == NULL)
2063 goto out;
2064
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302065 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 sap_config->acs_cfg.ch_list_count);
2067 }
2068 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2069 uint32_t *freq =
2070 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2071 sap_config->acs_cfg.ch_list_count = nla_len(
2072 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2073 sizeof(uint32_t);
2074 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302075 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002076 sap_config->acs_cfg.ch_list_count);
2077 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07002078 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 status = -ENOMEM;
2080 goto out;
2081 }
2082
2083 /* convert frequency to channel */
2084 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2085 sap_config->acs_cfg.ch_list[i] =
2086 ieee80211_frequency_to_channel(freq[i]);
2087 }
2088 }
2089
2090 hdd_debug("get pcl for DO_ACS vendor command");
2091
2092 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002093 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302094 sap_config->acs_cfg.pcl_channels,
2095 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302096 sap_config->acs_cfg.pcl_channels_weight_list,
2097 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302098 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002099 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302101 if (sap_config->acs_cfg.pcl_ch_count) {
2102 hdd_debug("ACS config PCL: len: %d",
2103 sap_config->acs_cfg.pcl_ch_count);
2104 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2105 hdd_debug("channel:%d, weight:%d ",
2106 sap_config->acs_cfg.
2107 pcl_channels[i],
2108 sap_config->acs_cfg.
2109 pcl_channels_weight_list[i]);
2110 }
2111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002112 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302113 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2114 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002115 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002116 vht_enabled = 1;
2117 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2118 sap_config->acs_cfg.ch_width =
2119 hdd_ctx->config->vhtChannelWidth;
2120 /* No VHT80 in 2.4G so perform ACS accordingly */
2121 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302122 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002123 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302124 ch_width = 40;
2125 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002126 }
2127
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302128 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2129
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002130 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 -08002131 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2132 ch_width, ht_enabled, vht_enabled,
2133 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2134
Kapil Gupta8878ad92017-02-13 11:56:04 +05302135 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2136 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2137
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002138 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002139 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002140 sap_config->acs_cfg.ch_list_count);
2141 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002142 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143 }
2144 sap_config->acs_cfg.acs_mode = true;
2145 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002146 /* ***Note*** Completion variable usage is not allowed
2147 * here since ACS scan operation may take max 2.2 sec
2148 * for 5G band:
2149 * 9 Active channel X 40 ms active scan time +
2150 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002151 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2152 * for this long. So we split up the scanning part.
2153 */
2154 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002155 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002156 status = 0;
2157 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302158 /* Check if vendor specific acs is enabled */
2159 if (hdd_ctx->config->vendor_acs_support) {
2160 sap_config->acs_cfg.hw_mode = hw_mode;
2161 hdd_create_acs_timer(adapter);
2162 hdd_update_acs_timer_reason(adapter,
2163 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2164 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2165 wlan_sap_set_vendor_acs(
2166 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2167 true);
2168 else
2169 wlan_sap_set_vendor_acs(
2170 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2171 false);
2172
2173 } else
2174 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002175 }
2176
2177out:
2178 if (0 == status) {
2179 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2180 NLMSG_HDRLEN);
2181 if (temp_skbuff != NULL)
2182 return cfg80211_vendor_cmd_reply(temp_skbuff);
2183 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002184 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2186
2187 return status;
2188}
2189
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002190/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2192 * @wiphy: Linux wiphy struct pointer
2193 * @wdev: Linux wireless device struct pointer
2194 * @data: ACS information from hostapd
2195 * @data_len: ACS information len
2196 *
2197 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2198 * and starts ACS procedure.
2199 *
2200 * Return: ACS procedure start status
2201 */
2202
2203static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2204 struct wireless_dev *wdev,
2205 const void *data, int data_len)
2206{
2207 int ret;
2208
2209 cds_ssr_protect(__func__);
2210 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2211 cds_ssr_unprotect(__func__);
2212
2213 return ret;
2214}
2215
2216/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002217 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2218 * @adapter: Pointer to adapter struct
2219 *
2220 * This function handle cleanup of what was done in DO_ACS, including free
2221 * memory.
2222 *
2223 * Return: void
2224 */
2225
2226void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2227{
2228 if (adapter == NULL)
2229 return;
2230 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2231 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2232 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2233 }
2234}
2235
2236/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002237 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2238 * @work: Linux workqueue struct pointer for ACS work
2239 *
2240 * This function starts the ACS procedure which was marked pending when an ACS
2241 * procedure was in progress for a concurrent SAP interface.
2242 *
2243 * Return: None
2244 */
2245
2246static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2247{
2248 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2249 acs_pending_work.work);
2250 wlan_hdd_cfg80211_start_acs(adapter);
2251}
2252
2253/**
2254 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2255 * @adapter: Pointer to SAP adapter struct
2256 * @pri_channel: SAP ACS procedure selected Primary channel
2257 * @sec_channel: SAP ACS procedure selected secondary channel
2258 *
2259 * This is a callback function from SAP module on ACS procedure is completed.
2260 * This function send the ACS selected channel information to hostapd
2261 *
2262 * Return: None
2263 */
2264
2265void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2266{
2267 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2268 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2269 struct sk_buff *vendor_event;
2270 int ret_val;
2271 hdd_adapter_t *con_sap_adapter;
2272 uint16_t ch_width;
2273
2274 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002275 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002276 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2277 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2278 GFP_KERNEL);
2279
2280 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002281 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002282 return;
2283 }
2284
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002285 ret_val = nla_put_u8(vendor_event,
2286 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2287 sap_cfg->acs_cfg.pri_ch);
2288 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002289 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002290 kfree_skb(vendor_event);
2291 return;
2292 }
2293
2294 ret_val = nla_put_u8(vendor_event,
2295 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2296 sap_cfg->acs_cfg.ht_sec_ch);
2297 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002298 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002299 kfree_skb(vendor_event);
2300 return;
2301 }
2302
2303 ret_val = nla_put_u8(vendor_event,
2304 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2305 sap_cfg->acs_cfg.vht_seg0_center_ch);
2306 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002307 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308 kfree_skb(vendor_event);
2309 return;
2310 }
2311
2312 ret_val = nla_put_u8(vendor_event,
2313 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2314 sap_cfg->acs_cfg.vht_seg1_center_ch);
2315 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002316 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317 kfree_skb(vendor_event);
2318 return;
2319 }
2320
2321 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2322 ch_width = 80;
2323 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2324 ch_width = 40;
2325 else
2326 ch_width = 20;
2327
2328 ret_val = nla_put_u16(vendor_event,
2329 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2330 ch_width);
2331 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002332 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333 kfree_skb(vendor_event);
2334 return;
2335 }
2336 if (sap_cfg->acs_cfg.pri_ch > 14)
2337 ret_val = nla_put_u8(vendor_event,
2338 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2339 QCA_ACS_MODE_IEEE80211A);
2340 else
2341 ret_val = nla_put_u8(vendor_event,
2342 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2343 QCA_ACS_MODE_IEEE80211G);
2344
2345 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002346 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347 kfree_skb(vendor_event);
2348 return;
2349 }
2350
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002351 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 -08002352 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2353 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2354 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2355
2356 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2357 /* ***Note*** As already mentioned Completion variable usage is not
2358 * allowed here since ACS scan operation may take max 2.2 sec.
2359 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2360 * operation.
2361 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2362 * when Primary AP ACS is complete and secondary AP ACS is started here
2363 * immediately, Primary AP start_bss may come inbetween ACS operation
2364 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2365 * delay. This path and below constraint will be removed on sessionizing
2366 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2367 * As per design constraint user space control application must take
2368 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2369 * this code path. Sec AP hostapd should be started after Primary AP
2370 * start beaconing which can be confirmed by getchannel iwpriv command
2371 */
2372
2373 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2374 if (con_sap_adapter &&
2375 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2377 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 /* Lets give 500ms for OBSS + START_BSS to complete */
2379 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2380 msecs_to_jiffies(500));
2381 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2382 }
2383
2384 return;
2385}
2386
2387static int
2388__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2389 struct wireless_dev *wdev,
2390 const void *data,
2391 int data_len)
2392{
2393 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2394 struct sk_buff *skb = NULL;
2395 uint32_t fset = 0;
2396 int ret;
2397
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002398 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302399
Anurag Chouhan6d760662016-02-20 16:05:43 +05302400 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401 hdd_err("Command not allowed in FTM mode");
2402 return -EPERM;
2403 }
2404
2405 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302406 if (ret)
2407 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002408
2409 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002410 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002411 fset |= WIFI_FEATURE_INFRA;
2412 }
2413 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002414 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002415 fset |= WIFI_FEATURE_INFRA_5G;
2416 }
2417#ifdef WLAN_FEATURE_P2P
2418 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2419 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002420 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002421 fset |= WIFI_FEATURE_P2P;
2422 }
2423#endif
2424 fset |= WIFI_FEATURE_SOFT_AP;
2425
2426 /* HOTSPOT is a supplicant feature, enable it by default */
2427 fset |= WIFI_FEATURE_HOTSPOT;
2428
2429#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302430 if (pHddCtx->config->extscan_enabled &&
2431 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002432 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002433 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2434 }
2435#endif
2436 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002437 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438 fset |= WIFI_FEATURE_NAN;
2439 }
2440 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002441 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 fset |= WIFI_FEATURE_D2D_RTT;
2443 fset |= WIFI_FEATURE_D2AP_RTT;
2444 }
2445#ifdef FEATURE_WLAN_SCAN_PNO
2446 if (pHddCtx->config->configPNOScanSupport &&
2447 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002448 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 fset |= WIFI_FEATURE_PNO;
2450 }
2451#endif
2452 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2453#ifdef FEATURE_WLAN_TDLS
2454 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2455 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002456 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 fset |= WIFI_FEATURE_TDLS;
2458 }
2459 if (sme_is_feature_supported_by_fw(TDLS) &&
2460 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2461 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002462 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2464 }
2465#endif
2466#ifdef WLAN_AP_STA_CONCURRENCY
2467 fset |= WIFI_FEATURE_AP_STA;
2468#endif
2469 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002470 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002471
2472 if (hdd_link_layer_stats_supported())
2473 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2474
2475 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2476 NLMSG_HDRLEN);
2477 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002478 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 return -EINVAL;
2480 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002481 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002483 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484 goto nla_put_failure;
2485 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302486 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302487 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488nla_put_failure:
2489 kfree_skb(skb);
2490 return -EINVAL;
2491}
2492
2493/**
2494 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2495 * @wiphy: pointer to wireless wiphy structure.
2496 * @wdev: pointer to wireless_dev structure.
2497 * @data: Pointer to the data to be passed via vendor interface
2498 * @data_len:Length of the data to be passed
2499 *
2500 * Return: Return the Success or Failure code.
2501 */
2502static int
2503wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2504 struct wireless_dev *wdev,
2505 const void *data, int data_len)
2506{
2507 int ret = 0;
2508
2509 cds_ssr_protect(__func__);
2510 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2511 data, data_len);
2512 cds_ssr_unprotect(__func__);
2513
2514 return ret;
2515}
2516
2517/**
2518 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2519 * @wiphy: pointer to wireless wiphy structure.
2520 * @wdev: pointer to wireless_dev structure.
2521 * @data: Pointer to the data to be passed via vendor interface
2522 * @data_len:Length of the data to be passed
2523 *
2524 * Set the MAC address that is to be used for scanning.
2525 *
2526 * Return: Return the Success or Failure code.
2527 */
2528static int
2529__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2530 struct wireless_dev *wdev,
2531 const void *data,
2532 int data_len)
2533{
2534 tpSirScanMacOui pReqMsg = NULL;
2535 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2536 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302537 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 int ret;
2539
Jeff Johnson1f61b612016-02-12 16:28:33 -08002540 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541
Anurag Chouhan6d760662016-02-20 16:05:43 +05302542 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002543 hdd_err("Command not allowed in FTM mode");
2544 return -EPERM;
2545 }
2546
2547 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302548 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550
2551 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002552 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 return -ENOTSUPP;
2554 }
2555
2556 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2557 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002558 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559 return -EINVAL;
2560 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302561 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002563 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564 return -ENOMEM;
2565 }
2566 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002567 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568 goto fail;
2569 }
2570 nla_memcpy(&pReqMsg->oui[0],
2571 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2572 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002573 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574 pReqMsg->oui[1], pReqMsg->oui[2]);
2575 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302576 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002577 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 goto fail;
2579 }
2580 return 0;
2581fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302582 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002583 return -EINVAL;
2584}
2585
2586/**
2587 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2588 * @wiphy: pointer to wireless wiphy structure.
2589 * @wdev: pointer to wireless_dev structure.
2590 * @data: Pointer to the data to be passed via vendor interface
2591 * @data_len:Length of the data to be passed
2592 *
2593 * Set the MAC address that is to be used for scanning. This is an
2594 * SSR-protecting wrapper function.
2595 *
2596 * Return: Return the Success or Failure code.
2597 */
2598static int
2599wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2600 struct wireless_dev *wdev,
2601 const void *data,
2602 int data_len)
2603{
2604 int ret;
2605
2606 cds_ssr_protect(__func__);
2607 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2608 data, data_len);
2609 cds_ssr_unprotect(__func__);
2610
2611 return ret;
2612}
2613
2614/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302615 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2616 * @wiphy: pointer phy adapter
2617 * @wdev: pointer to wireless device structure
2618 * @data: pointer to data buffer
2619 * @data_len: length of data
2620 *
2621 * This routine will give concurrency matrix
2622 *
2623 * Return: int status code
2624 */
2625static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2626 struct wireless_dev *wdev,
2627 const void *data,
2628 int data_len)
2629{
2630 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2631 uint8_t i, feature_sets, max_feature_sets;
2632 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2633 struct sk_buff *reply_skb;
2634 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2635 int ret;
2636
2637 ENTER_DEV(wdev->netdev);
2638
2639 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2640 hdd_err("Command not allowed in FTM mode");
2641 return -EPERM;
2642 }
2643
2644 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302645 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302646 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302647
2648 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2649 data, data_len, NULL)) {
2650 hdd_err("Invalid ATTR");
2651 return -EINVAL;
2652 }
2653
2654 /* Parse and fetch max feature set */
2655 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2656 hdd_err("Attr max feature set size failed");
2657 return -EINVAL;
2658 }
2659 max_feature_sets = nla_get_u32(tb[
2660 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002661 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302662
2663 /* Fill feature combination matrix */
2664 feature_sets = 0;
2665 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002666 WIFI_FEATURE_P2P;
2667 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2668 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302669 /* Add more feature combinations here */
2670
2671 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002672 hdd_debug("Number of feature sets: %d", feature_sets);
2673 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302674 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002675 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302676
2677 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2678 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2679 if (!reply_skb) {
2680 hdd_err("Feature set matrix: buffer alloc fail");
2681 return -ENOMEM;
2682 }
2683
2684 if (nla_put_u32(reply_skb,
2685 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2686 feature_sets) ||
2687 nla_put(reply_skb,
2688 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2689 sizeof(u32) * feature_sets,
2690 feature_set_matrix)) {
2691 hdd_err("nla put fail");
2692 kfree_skb(reply_skb);
2693 return -EINVAL;
2694 }
2695 return cfg80211_vendor_cmd_reply(reply_skb);
2696}
2697
2698/**
2699 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2700 * @wiphy: pointer to wireless wiphy structure.
2701 * @wdev: pointer to wireless_dev structure.
2702 * @data: Pointer to the data to be passed via vendor interface
2703 * @data_len:Length of the data to be passed
2704 *
2705 * Retrieves the concurrency feature set matrix
2706 *
2707 * Return: 0 on success, negative errno on failure
2708 */
2709static int
2710wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2711 struct wireless_dev *wdev,
2712 const void *data,
2713 int data_len)
2714{
2715 int ret;
2716
2717 cds_ssr_protect(__func__);
2718 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2719 data, data_len);
2720 cds_ssr_unprotect(__func__);
2721
2722 return ret;
2723}
2724
2725/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002726 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2727 * @feature_flags: pointer to the byte array of features.
2728 * @feature: Feature to be turned ON in the byte array.
2729 *
2730 * Return: None
2731 *
2732 * This is called to turn ON or SET the feature flag for the requested feature.
2733 **/
2734#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002735static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2736 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002737{
2738 uint32_t index;
2739 uint8_t bit_mask;
2740
2741 index = feature / NUM_BITS_IN_BYTE;
2742 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2743 feature_flags[index] |= bit_mask;
2744}
2745
2746/**
2747 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2748 * @wiphy: pointer to wireless wiphy structure.
2749 * @wdev: pointer to wireless_dev structure.
2750 * @data: Pointer to the data to be passed via vendor interface
2751 * @data_len:Length of the data to be passed
2752 *
2753 * This is called when wlan driver needs to send supported feature set to
2754 * supplicant upon a request/query from the supplicant.
2755 *
2756 * Return: Return the Success or Failure code.
2757 **/
2758#define MAX_CONCURRENT_CHAN_ON_24G 2
2759#define MAX_CONCURRENT_CHAN_ON_5G 2
2760static int
2761__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2762 struct wireless_dev *wdev,
2763 const void *data, int data_len)
2764{
2765 struct sk_buff *skb = NULL;
2766 uint32_t dbs_capability = 0;
2767 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302768 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769 int ret_val;
2770
2771 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2772 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2773
Jeff Johnson1f61b612016-02-12 16:28:33 -08002774 ENTER_DEV(wdev->netdev);
2775
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2777 if (ret_val)
2778 return ret_val;
2779
Anurag Chouhan6d760662016-02-20 16:05:43 +05302780 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002781 hdd_err("Command not allowed in FTM mode");
2782 return -EPERM;
2783 }
2784
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002785 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002786 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 wlan_hdd_cfg80211_set_feature(feature_flags,
2788 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2789 }
2790
2791 wlan_hdd_cfg80211_set_feature(feature_flags,
2792 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002793 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002794 wlan_hdd_cfg80211_set_feature(feature_flags,
2795 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002796
2797 if (wma_is_p2p_lo_capable())
2798 wlan_hdd_cfg80211_set_feature(feature_flags,
2799 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2800
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2802 NLMSG_HDRLEN);
2803
2804 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002805 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806 return -ENOMEM;
2807 }
2808
2809 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2810 sizeof(feature_flags), feature_flags))
2811 goto nla_put_failure;
2812
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002813 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2814 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302815 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 if (one_by_one_dbs)
2817 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2818
2819 if (two_by_two_dbs)
2820 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2821
2822 if (!one_by_one_dbs && !two_by_two_dbs)
2823 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2824 } else {
2825 hdd_err("wma_get_dbs_hw_mode failed");
2826 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2827 }
2828
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002829 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830
2831 if (nla_put_u32(skb,
2832 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2833 MAX_CONCURRENT_CHAN_ON_24G))
2834 goto nla_put_failure;
2835
2836 if (nla_put_u32(skb,
2837 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2838 MAX_CONCURRENT_CHAN_ON_5G))
2839 goto nla_put_failure;
2840
2841 return cfg80211_vendor_cmd_reply(skb);
2842
2843nla_put_failure:
2844 kfree_skb(skb);
2845 return -EINVAL;
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 */
2860static int
2861wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2862 struct wireless_dev *wdev,
2863 const void *data, int data_len)
2864{
2865 int ret;
2866
2867 cds_ssr_protect(__func__);
2868 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2869 data, data_len);
2870 cds_ssr_unprotect(__func__);
2871
2872 return ret;
2873}
2874
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302875#define PARAM_NUM_NW \
2876 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2877#define PARAM_SET_BSSID \
2878 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2879#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2880#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002881
2882/**
2883 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2884 * @wiphy: The wiphy structure
2885 * @wdev: The wireless device
2886 * @data: Data passed by framework
2887 * @data_len: Parameters to be configured passed as data
2888 *
2889 * The roaming related parameters are configured by the framework
2890 * using this interface.
2891 *
2892 * Return: Return either success or failure code.
2893 */
2894static int
2895__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2896 struct wireless_dev *wdev, const void *data, int data_len)
2897{
2898 struct net_device *dev = wdev->netdev;
2899 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2900 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2901 uint8_t session_id;
2902 struct roam_ext_params roam_params;
2903 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302904 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2906 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2907 int rem, i;
2908 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002909 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910 int ret;
2911
Jeff Johnson1f61b612016-02-12 16:28:33 -08002912 ENTER_DEV(dev);
2913
Anurag Chouhan6d760662016-02-20 16:05:43 +05302914 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 hdd_err("Command not allowed in FTM mode");
2916 return -EPERM;
2917 }
2918
2919 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302920 if (ret)
2921 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05302923 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
2924 hdd_err("Driver Modules are closed");
2925 return -EINVAL;
2926 }
2927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2929 data, data_len,
2930 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002931 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932 return -EINVAL;
2933 }
2934 /* Parse and fetch Command Type*/
2935 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002936 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002937 goto fail;
2938 }
2939 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302940 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2942 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002943 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944 goto fail;
2945 }
2946 req_id = nla_get_u32(
2947 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002948 hdd_debug("Req Id (%d)", req_id);
2949 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 switch (cmd_type) {
2951 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2952 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302953 if (tb[PARAM_NUM_NW]) {
2954 count = nla_get_u32(
2955 tb[PARAM_NUM_NW]);
2956 } else {
2957 hdd_err("Number of networks is not provided");
2958 goto fail;
2959 }
2960
2961 if (count &&
2962 tb[PRAM_SSID_LIST]) {
2963 nla_for_each_nested(curr_attr,
2964 tb[PRAM_SSID_LIST], rem) {
2965 if (nla_parse(tb2,
2966 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2967 nla_data(curr_attr), nla_len(curr_attr),
2968 NULL)) {
2969 hdd_err("nla_parse failed");
2970 goto fail;
2971 }
2972 /* Parse and Fetch allowed SSID list*/
2973 if (!tb2[PARAM_LIST_SSID]) {
2974 hdd_err("attr allowed ssid failed");
2975 goto fail;
2976 }
2977 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2978 /*
2979 * Upper Layers include a null termination
2980 * character. Check for the actual permissible
2981 * length of SSID and also ensure not to copy
2982 * the NULL termination character to the driver
2983 * buffer.
2984 */
2985 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2986 ((buf_len - 1) <=
2987 SIR_MAC_MAX_SSID_LENGTH)) {
2988 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302990 tb2[PARAM_LIST_SSID], buf_len - 1);
2991 roam_params.ssid_allowed_list[i].length
2992 = buf_len - 1;
2993 hdd_debug("SSID[%d]: %.*s,length = %d",
2994 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 roam_params.ssid_allowed_list[i].length,
2996 roam_params.ssid_allowed_list[i].ssId,
2997 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302998 i++;
2999 } else {
3000 hdd_err("Invalid buffer length");
3001 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 }
3003 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303004 if (i != count) {
3005 hdd_err("Invalid number of SSIDs i = %d, count = %d",
3006 i, count);
3007 goto fail;
3008 }
3009
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07003011 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012 roam_params.num_ssid_allowed_list);
3013 sme_update_roam_params(pHddCtx->hHal, session_id,
3014 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3015 break;
3016 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3017 /* Parse and fetch 5G Boost Threshold */
3018 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003019 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003020 goto fail;
3021 }
3022 roam_params.raise_rssi_thresh_5g = nla_get_s32(
3023 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003024 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003025 roam_params.raise_rssi_thresh_5g);
3026 /* Parse and fetch 5G Penalty Threshold */
3027 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003028 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029 goto fail;
3030 }
3031 roam_params.drop_rssi_thresh_5g = nla_get_s32(
3032 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003033 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 roam_params.drop_rssi_thresh_5g);
3035 /* Parse and fetch 5G Boost Factor */
3036 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003037 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 goto fail;
3039 }
3040 roam_params.raise_factor_5g = nla_get_u32(
3041 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003042 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 roam_params.raise_factor_5g);
3044 /* Parse and fetch 5G Penalty factor */
3045 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003046 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003047 goto fail;
3048 }
3049 roam_params.drop_factor_5g = nla_get_u32(
3050 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003051 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 roam_params.drop_factor_5g);
3053 /* Parse and fetch 5G Max Boost */
3054 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003055 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 goto fail;
3057 }
3058 roam_params.max_raise_rssi_5g = nla_get_u32(
3059 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07003060 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 roam_params.max_raise_rssi_5g);
3062 /* Parse and fetch Rssi Diff */
3063 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003064 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065 goto fail;
3066 }
3067 roam_params.rssi_diff = nla_get_s32(
3068 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07003069 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003070 roam_params.rssi_diff);
3071 /* Parse and fetch Alert Rssi Threshold */
3072 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003073 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003074 goto fail;
3075 }
3076 roam_params.alert_rssi_threshold = nla_get_u32(
3077 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003078 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003079 roam_params.alert_rssi_threshold);
3080 sme_update_roam_params(pHddCtx->hHal, session_id,
3081 roam_params,
3082 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3083 break;
3084 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3085 /* Parse and fetch Activate Good Rssi Roam */
3086 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003087 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003088 goto fail;
3089 }
3090 roam_params.good_rssi_roam = nla_get_s32(
3091 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07003092 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003093 roam_params.good_rssi_roam);
3094 sme_update_roam_params(pHddCtx->hHal, session_id,
3095 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3096 break;
3097 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3098 /* Parse and fetch number of preferred BSSID */
3099 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003100 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003101 goto fail;
3102 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003103 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003105 if (count > MAX_BSSID_FAVORED) {
3106 hdd_err("Preferred BSSID count %u exceeds max %u",
3107 count, MAX_BSSID_FAVORED);
3108 goto fail;
3109 }
3110 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111 i = 0;
3112 nla_for_each_nested(curr_attr,
3113 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3114 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003115
3116 if (i == count) {
3117 hdd_warn("Ignoring excess Preferred BSSID");
3118 break;
3119 }
3120
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003121 if (nla_parse(tb2,
3122 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3123 nla_data(curr_attr), nla_len(curr_attr),
3124 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003125 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003126 goto fail;
3127 }
3128 /* Parse and fetch MAC address */
3129 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003130 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003131 goto fail;
3132 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003133 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003134 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303135 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003136 hdd_debug(MAC_ADDRESS_STR,
3137 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003138 /* Parse and fetch preference factor*/
3139 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003140 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 goto fail;
3142 }
3143 roam_params.bssid_favored_factor[i] = nla_get_u32(
3144 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003145 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 roam_params.bssid_favored_factor[i]);
3147 i++;
3148 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003149 if (i < count)
3150 hdd_warn("Num Preferred BSSID %u less than expected %u",
3151 i, count);
3152 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003153 sme_update_roam_params(pHddCtx->hHal, session_id,
3154 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3155 break;
3156 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3157 /* Parse and fetch number of blacklist BSSID */
3158 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003159 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160 goto fail;
3161 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003162 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003164 if (count > MAX_BSSID_AVOID_LIST) {
3165 hdd_err("Blacklist BSSID count %u exceeds max %u",
3166 count, MAX_BSSID_AVOID_LIST);
3167 goto fail;
3168 }
3169 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303171
3172 if (count &&
3173 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3174 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3176 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003177
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303178 if (i == count) {
3179 hdd_warn("Ignoring excess Blacklist BSSID");
3180 break;
3181 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003182
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303183 if (nla_parse(tb2,
3184 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3185 nla_data(curr_attr), nla_len(curr_attr),
3186 NULL)) {
3187 hdd_err("nla_parse failed");
3188 goto fail;
3189 }
3190 /* Parse and fetch MAC address */
3191 if (!tb2[PARAM_SET_BSSID]) {
3192 hdd_err("attr blacklist addr failed");
3193 goto fail;
3194 }
3195 nla_memcpy(
3196 roam_params.bssid_avoid_list[i].bytes,
3197 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3198 hdd_debug(MAC_ADDRESS_STR,
3199 MAC_ADDR_ARRAY(
3200 roam_params.bssid_avoid_list[i].bytes));
3201 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003204 if (i < count)
3205 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3206 i, count);
3207 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208 sme_update_roam_params(pHddCtx->hHal, session_id,
3209 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3210 break;
3211 }
3212 return 0;
3213fail:
3214 return -EINVAL;
3215}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303216#undef PARAM_NUM_NW
3217#undef PARAM_SET_BSSID
3218#undef PRAM_SSID_LIST
3219#undef PARAM_LIST_SSID
3220
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003221
3222/**
3223 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3224 * @wiphy: pointer to wireless wiphy structure.
3225 * @wdev: pointer to wireless_dev structure.
3226 * @data: Pointer to the data to be passed via vendor interface
3227 * @data_len:Length of the data to be passed
3228 *
3229 * Return: Return the Success or Failure code.
3230 */
3231static int
3232wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3233 struct wireless_dev *wdev,
3234 const void *data,
3235 int data_len)
3236{
3237 int ret;
3238
3239 cds_ssr_protect(__func__);
3240 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3241 data, data_len);
3242 cds_ssr_unprotect(__func__);
3243
3244 return ret;
3245}
3246
3247static const struct nla_policy
3248wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3249 +1] = {
3250 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3251};
3252
3253/**
3254 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3255 * @hdd_ctx: HDD context
3256 * @device_mode: device mode
3257 * Return: bool
3258 */
3259static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003260 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261{
3262 hdd_adapter_t *adapter;
3263 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3264 hdd_ap_ctx_t *ap_ctx;
3265 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303266 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303268 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003269 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303271 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 adapter = adapter_node->pAdapter;
3273
3274 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003275 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 ap_ctx =
3277 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3278
3279 /*
3280 * if there is SAP already running on DFS channel,
3281 * do not disable scan on dfs channels. Note that
3282 * with SAP on DFS, there cannot be conurrency on
3283 * single radio. But then we can have multiple
3284 * radios !!
3285 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003286 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3287 hdd_ctx->hdd_pdev,
3288 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003289 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003290 return true;
3291 }
3292 }
3293
3294 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003295 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003296 sta_ctx =
3297 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3298
3299 /*
3300 * if STA is already connected on DFS channel,
3301 * do not disable scan on dfs channels
3302 */
3303 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003304 (CHANNEL_STATE_DFS ==
3305 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3306 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003307 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003308 return true;
3309 }
3310 }
3311
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303312 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003313 adapter_node,
3314 &next);
3315 adapter_node = next;
3316 }
3317
3318 return false;
3319}
3320
3321/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003322 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003323 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003324 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003325 *
3326 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003327 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003328 * Fails the disable request if any device is active on a DFS channel.
3329 *
3330 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003332
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003333int wlan_hdd_enable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3334 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303336 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003337 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003339 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
3340 hdd_info("DFS channels are already %s",
3341 enable_dfs_channels ? "enabled" : "disabled");
3342 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003344
3345 if (!enable_dfs_channels) {
3346 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3347 QDF_STA_MODE);
3348 if (err)
3349 return -EOPNOTSUPP;
3350
3351 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3352 QDF_SAP_MODE);
3353 if (err)
3354 return -EOPNOTSUPP;
3355 }
3356
3357 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
3358
3359 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3360
3361 /* pass dfs channel status to regulatory component */
3362 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
3363 enable_dfs_channels);
3364
3365 if (QDF_IS_STATUS_ERROR(status))
3366 hdd_err("Failed to %s DFS channels",
3367 enable_dfs_channels ? "enable" : "disable");
3368
3369 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003370}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003371
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003372/**
3373 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3374 * @wiphy: corestack handler
3375 * @wdev: wireless device
3376 * @data: data
3377 * @data_len: data length
3378 * Return: success(0) or reason code for failure
3379 */
3380static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3381 struct wireless_dev *wdev,
3382 const void *data,
3383 int data_len)
3384{
3385 struct net_device *dev = wdev->netdev;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003386 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3387 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3388 int ret_val;
3389 uint32_t no_dfs_flag = 0;
3390
Jeff Johnson1f61b612016-02-12 16:28:33 -08003391 ENTER_DEV(dev);
3392
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003393 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303394 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003395 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003396
3397 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3398 data, data_len,
3399 wlan_hdd_set_no_dfs_flag_config_policy)) {
3400 hdd_err("invalid attr");
3401 return -EINVAL;
3402 }
3403
3404 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3405 hdd_err("attr dfs flag failed");
3406 return -EINVAL;
3407 }
3408
3409 no_dfs_flag = nla_get_u32(
3410 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3411
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003412 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003413
3414 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003415 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003416 return -EINVAL;
3417 }
3418
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003419 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003420 return ret_val;
3421}
3422
3423/**
3424 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3425 *
3426 * @wiphy: wiphy device pointer
3427 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003428 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 * @data_len: Buffer length
3430 *
3431 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3432 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3433 *
3434 * Return: EOK or other error codes.
3435 */
3436
3437static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3438 struct wireless_dev *wdev,
3439 const void *data,
3440 int data_len)
3441{
3442 int ret;
3443
3444 cds_ssr_protect(__func__);
3445 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3446 data, data_len);
3447 cds_ssr_unprotect(__func__);
3448
3449 return ret;
3450}
3451
Manikandan Mohan80dea792016-04-28 16:36:48 -07003452static const struct nla_policy
3453wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3454 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3455};
3456
3457/**
3458 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3459 * @wiphy: wiphy device pointer
3460 * @wdev: wireless device pointer
3461 * @data: Vendor command data buffer
3462 * @data_len: Buffer length
3463 *
3464 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3465 * setup WISA Mode features.
3466 *
3467 * Return: Success(0) or reason code for failure
3468 */
3469static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3470 struct wireless_dev *wdev, const void *data, int data_len)
3471{
3472 struct net_device *dev = wdev->netdev;
3473 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3474 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3475 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3476 struct sir_wisa_params wisa;
3477 int ret_val;
3478 QDF_STATUS status;
3479 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003480 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3481 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003482
3483 ENTER_DEV(dev);
3484 ret_val = wlan_hdd_validate_context(hdd_ctx);
3485 if (ret_val)
3486 goto err;
3487
3488 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3489 hdd_err("Command not allowed in FTM mode");
3490 return -EPERM;
3491 }
3492
3493 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3494 wlan_hdd_wisa_cmd_policy)) {
3495 hdd_err("Invalid WISA cmd attributes");
3496 ret_val = -EINVAL;
3497 goto err;
3498 }
3499 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3500 hdd_err("Invalid WISA mode");
3501 ret_val = -EINVAL;
3502 goto err;
3503 }
3504
3505 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003506 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003507 wisa.mode = wisa_mode;
3508 wisa.vdev_id = adapter->sessionId;
3509 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003510 if (!QDF_IS_STATUS_SUCCESS(status)) {
3511 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003512 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003513 }
3514 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003515 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003516 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3517 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003518 adapter->sessionId),
3519 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003520err:
3521 EXIT();
3522 return ret_val;
3523}
3524
3525/**
3526 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3527 * @wiphy: corestack handler
3528 * @wdev: wireless device
3529 * @data: data
3530 * @data_len: data length
3531 *
3532 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3533 * setup WISA mode features.
3534 *
3535 * Return: Success(0) or reason code for failure
3536 */
3537static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3538 struct wireless_dev *wdev,
3539 const void *data,
3540 int data_len)
3541{
3542 int ret;
3543
3544 cds_ssr_protect(__func__);
3545 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3546 cds_ssr_unprotect(__func__);
3547
3548 return ret;
3549}
3550
Anurag Chouhan96919482016-07-13 16:36:57 +05303551/*
3552 * define short names for the global vendor params
3553 * used by __wlan_hdd_cfg80211_get_station_cmd()
3554 */
3555#define STATION_INVALID \
3556 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3557#define STATION_INFO \
3558 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3559#define STATION_ASSOC_FAIL_REASON \
3560 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3561#define STATION_MAX \
3562 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3563
3564static const struct nla_policy
3565hdd_get_station_policy[STATION_MAX + 1] = {
3566 [STATION_INFO] = {.type = NLA_FLAG},
3567 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3568};
3569
3570/**
3571 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3572 * @hdd_ctx: HDD context within host driver
3573 * @wdev: wireless device
3574 *
3575 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3576 * Validate cmd attributes and send the station info to upper layers.
3577 *
3578 * Return: Success(0) or reason code for failure
3579 */
3580static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3581 hdd_adapter_t *adapter)
3582{
3583 struct sk_buff *skb = NULL;
3584 uint32_t nl_buf_len;
3585 hdd_station_ctx_t *hdd_sta_ctx;
3586
3587 nl_buf_len = NLMSG_HDRLEN;
3588 nl_buf_len += sizeof(uint32_t);
3589 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3590
3591 if (!skb) {
3592 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3593 return -ENOMEM;
3594 }
3595
3596 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3597
3598 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3599 hdd_sta_ctx->conn_info.assoc_status_code)) {
3600 hdd_err("put fail");
3601 goto fail;
3602 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303603
3604 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3605 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3606 hdd_sta_ctx->conn_info.cca)) {
3607 hdd_err("put fail");
3608 goto fail;
3609 }
3610
Anurag Chouhan96919482016-07-13 16:36:57 +05303611 return cfg80211_vendor_cmd_reply(skb);
3612fail:
3613 if (skb)
3614 kfree_skb(skb);
3615 return -EINVAL;
3616}
3617
3618/**
3619 * hdd_map_auth_type() - transform auth type specific to
3620 * vendor command
3621 * @auth_type: csr auth type
3622 *
3623 * Return: Success(0) or reason code for failure
3624 */
3625static int hdd_convert_auth_type(uint32_t auth_type)
3626{
3627 uint32_t ret_val;
3628
3629 switch (auth_type) {
3630 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3631 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3632 break;
3633 case eCSR_AUTH_TYPE_SHARED_KEY:
3634 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3635 break;
3636 case eCSR_AUTH_TYPE_WPA:
3637 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3638 break;
3639 case eCSR_AUTH_TYPE_WPA_PSK:
3640 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3641 break;
3642 case eCSR_AUTH_TYPE_AUTOSWITCH:
3643 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3644 break;
3645 case eCSR_AUTH_TYPE_WPA_NONE:
3646 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3647 break;
3648 case eCSR_AUTH_TYPE_RSN:
3649 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3650 break;
3651 case eCSR_AUTH_TYPE_RSN_PSK:
3652 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3653 break;
3654 case eCSR_AUTH_TYPE_FT_RSN:
3655 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3656 break;
3657 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3658 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3659 break;
3660 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3661 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3662 break;
3663 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3664 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3665 break;
3666 case eCSR_AUTH_TYPE_CCKM_WPA:
3667 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3668 break;
3669 case eCSR_AUTH_TYPE_CCKM_RSN:
3670 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3671 break;
3672 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3673 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3674 break;
3675 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3676 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3677 break;
3678 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3679 case eCSR_AUTH_TYPE_FAILED:
3680 case eCSR_AUTH_TYPE_NONE:
3681 default:
3682 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3683 break;
3684 }
3685 return ret_val;
3686}
3687
3688/**
3689 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3690 * vendor command
3691 * @dot11mode: dot11mode
3692 *
3693 * Return: Success(0) or reason code for failure
3694 */
3695static int hdd_convert_dot11mode(uint32_t dot11mode)
3696{
3697 uint32_t ret_val;
3698
3699 switch (dot11mode) {
3700 case eCSR_CFG_DOT11_MODE_11A:
3701 ret_val = QCA_WLAN_802_11_MODE_11A;
3702 break;
3703 case eCSR_CFG_DOT11_MODE_11B:
3704 ret_val = QCA_WLAN_802_11_MODE_11B;
3705 break;
3706 case eCSR_CFG_DOT11_MODE_11G:
3707 ret_val = QCA_WLAN_802_11_MODE_11G;
3708 break;
3709 case eCSR_CFG_DOT11_MODE_11N:
3710 ret_val = QCA_WLAN_802_11_MODE_11N;
3711 break;
3712 case eCSR_CFG_DOT11_MODE_11AC:
3713 ret_val = QCA_WLAN_802_11_MODE_11AC;
3714 break;
3715 case eCSR_CFG_DOT11_MODE_AUTO:
3716 case eCSR_CFG_DOT11_MODE_ABG:
3717 default:
3718 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3719 }
3720 return ret_val;
3721}
3722
3723/**
3724 * hdd_add_tx_bitrate() - add tx bitrate attribute
3725 * @skb: pointer to sk buff
3726 * @hdd_sta_ctx: pointer to hdd station context
3727 * @idx: attribute index
3728 *
3729 * Return: Success(0) or reason code for failure
3730 */
3731static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3732 hdd_station_ctx_t *hdd_sta_ctx,
3733 int idx)
3734{
3735 struct nlattr *nla_attr;
3736 uint32_t bitrate, bitrate_compat;
3737
3738 nla_attr = nla_nest_start(skb, idx);
3739 if (!nla_attr)
3740 goto fail;
3741 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3742 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3743
3744 /* report 16-bit bitrate only if we can */
3745 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3746 if (bitrate > 0 &&
3747 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3748 hdd_err("put fail");
3749 goto fail;
3750 }
3751 if (bitrate_compat > 0 &&
3752 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3753 hdd_err("put fail");
3754 goto fail;
3755 }
3756 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3757 hdd_sta_ctx->conn_info.txrate.nss)) {
3758 hdd_err("put fail");
3759 goto fail;
3760 }
3761 nla_nest_end(skb, nla_attr);
3762 return 0;
3763fail:
3764 return -EINVAL;
3765}
3766
3767/**
3768 * hdd_add_sta_info() - add station info attribute
3769 * @skb: pointer to sk buff
3770 * @hdd_sta_ctx: pointer to hdd station context
3771 * @idx: attribute index
3772 *
3773 * Return: Success(0) or reason code for failure
3774 */
3775static int32_t hdd_add_sta_info(struct sk_buff *skb,
3776 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3777{
3778 struct nlattr *nla_attr;
3779
3780 nla_attr = nla_nest_start(skb, idx);
3781 if (!nla_attr)
3782 goto fail;
3783 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3784 (hdd_sta_ctx->conn_info.signal + 100))) {
3785 hdd_err("put fail");
3786 goto fail;
3787 }
3788 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3789 goto fail;
3790 nla_nest_end(skb, nla_attr);
3791 return 0;
3792fail:
3793 return -EINVAL;
3794}
3795
3796/**
3797 * hdd_add_survey_info() - add survey info attribute
3798 * @skb: pointer to sk buff
3799 * @hdd_sta_ctx: pointer to hdd station context
3800 * @idx: attribute index
3801 *
3802 * Return: Success(0) or reason code for failure
3803 */
3804static int32_t hdd_add_survey_info(struct sk_buff *skb,
3805 hdd_station_ctx_t *hdd_sta_ctx,
3806 int idx)
3807{
3808 struct nlattr *nla_attr;
3809
3810 nla_attr = nla_nest_start(skb, idx);
3811 if (!nla_attr)
3812 goto fail;
3813 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3814 hdd_sta_ctx->conn_info.freq) ||
3815 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3816 (hdd_sta_ctx->conn_info.noise + 100))) {
3817 hdd_err("put fail");
3818 goto fail;
3819 }
3820 nla_nest_end(skb, nla_attr);
3821 return 0;
3822fail:
3823 return -EINVAL;
3824}
3825
3826/**
3827 * hdd_add_link_standard_info() - add link info attribute
3828 * @skb: pointer to sk buff
3829 * @hdd_sta_ctx: pointer to hdd station context
3830 * @idx: attribute index
3831 *
3832 * Return: Success(0) or reason code for failure
3833 */
3834static int32_t
3835hdd_add_link_standard_info(struct sk_buff *skb,
3836 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3837{
3838 struct nlattr *nla_attr;
3839
3840 nla_attr = nla_nest_start(skb, idx);
3841 if (!nla_attr)
3842 goto fail;
3843 if (nla_put(skb,
3844 NL80211_ATTR_SSID,
3845 hdd_sta_ctx->conn_info.SSID.SSID.length,
3846 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3847 hdd_err("put fail");
3848 goto fail;
3849 }
3850 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3851 goto fail;
3852 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3853 goto fail;
3854 nla_nest_end(skb, nla_attr);
3855 return 0;
3856fail:
3857 return -EINVAL;
3858}
3859
3860/**
3861 * hdd_add_ap_standard_info() - add ap info attribute
3862 * @skb: pointer to sk buff
3863 * @hdd_sta_ctx: pointer to hdd station context
3864 * @idx: attribute index
3865 *
3866 * Return: Success(0) or reason code for failure
3867 */
3868static int32_t
3869hdd_add_ap_standard_info(struct sk_buff *skb,
3870 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3871{
3872 struct nlattr *nla_attr;
3873
3874 nla_attr = nla_nest_start(skb, idx);
3875 if (!nla_attr)
3876 goto fail;
3877 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3878 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3879 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3880 &hdd_sta_ctx->conn_info.vht_caps)) {
3881 hdd_err("put fail");
3882 goto fail;
3883 }
3884 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3885 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3886 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3887 &hdd_sta_ctx->conn_info.ht_caps)) {
3888 hdd_err("put fail");
3889 goto fail;
3890 }
3891 nla_nest_end(skb, nla_attr);
3892 return 0;
3893fail:
3894 return -EINVAL;
3895}
3896
3897/**
3898 * hdd_get_station_info() - send BSS information to supplicant
3899 * @hdd_ctx: pointer to hdd context
3900 * @adapter: pointer to adapter
3901 *
3902 * Return: 0 if success else error status
3903 */
3904static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3905 hdd_adapter_t *adapter)
3906{
3907 struct sk_buff *skb = NULL;
3908 uint8_t *tmp_hs20 = NULL;
3909 uint32_t nl_buf_len;
3910 hdd_station_ctx_t *hdd_sta_ctx;
3911
3912 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3913
3914 nl_buf_len = NLMSG_HDRLEN;
3915 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3916 sizeof(hdd_sta_ctx->conn_info.freq) +
3917 sizeof(hdd_sta_ctx->conn_info.noise) +
3918 sizeof(hdd_sta_ctx->conn_info.signal) +
3919 (sizeof(uint32_t) * 2) +
3920 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3921 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3922 sizeof(hdd_sta_ctx->conn_info.authType) +
3923 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3924 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3925 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3926 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3927 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3928 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3929 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3930 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3931 1);
3932 }
3933 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3934 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3935 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3936 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3937
3938
3939 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3940 if (!skb) {
3941 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3942 return -ENOMEM;
3943 }
3944
3945 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3946 LINK_INFO_STANDARD_NL80211_ATTR)) {
3947 hdd_err("put fail");
3948 goto fail;
3949 }
3950 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3951 AP_INFO_STANDARD_NL80211_ATTR)) {
3952 hdd_err("put fail");
3953 goto fail;
3954 }
3955 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3956 hdd_sta_ctx->conn_info.roam_count) ||
3957 nla_put_u32(skb, INFO_AKM,
3958 hdd_convert_auth_type(
3959 hdd_sta_ctx->conn_info.authType)) ||
3960 nla_put_u32(skb, WLAN802_11_MODE,
3961 hdd_convert_dot11mode(
3962 hdd_sta_ctx->conn_info.dot11Mode))) {
3963 hdd_err("put fail");
3964 goto fail;
3965 }
3966 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3967 if (nla_put(skb, HT_OPERATION,
3968 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3969 &hdd_sta_ctx->conn_info.ht_operation)) {
3970 hdd_err("put fail");
3971 goto fail;
3972 }
3973 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3974 if (nla_put(skb, VHT_OPERATION,
3975 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3976 &hdd_sta_ctx->conn_info.vht_operation)) {
3977 hdd_err("put fail");
3978 goto fail;
3979 }
3980 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3981 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3982 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3983 tmp_hs20 + 1)) {
3984 hdd_err("put fail");
3985 goto fail;
3986 }
3987
3988 return cfg80211_vendor_cmd_reply(skb);
3989fail:
3990 if (skb)
3991 kfree_skb(skb);
3992 return -EINVAL;
3993}
3994
3995/**
3996 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3997 * @wiphy: corestack handler
3998 * @wdev: wireless device
3999 * @data: data
4000 * @data_len: data length
4001 *
4002 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4003 * Validate cmd attributes and send the station info to upper layers.
4004 *
4005 * Return: Success(0) or reason code for failure
4006 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05304007static int
Anurag Chouhan96919482016-07-13 16:36:57 +05304008__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4009 struct wireless_dev *wdev,
4010 const void *data,
4011 int data_len)
4012{
4013 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4014 struct net_device *dev = wdev->netdev;
4015 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4016 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
4017 int32_t status;
4018
4019 ENTER_DEV(dev);
4020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4021 hdd_err("Command not allowed in FTM mode");
4022 status = -EPERM;
4023 goto out;
4024 }
4025
4026 status = wlan_hdd_validate_context(hdd_ctx);
4027 if (0 != status)
4028 goto out;
4029
4030
4031 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
4032 data, data_len, NULL);
4033 if (status) {
4034 hdd_err("Invalid ATTR");
4035 goto out;
4036 }
4037
4038 /* Parse and fetch Command Type*/
4039 if (tb[STATION_INFO]) {
4040 status = hdd_get_station_info(hdd_ctx, adapter);
4041 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
4042 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
4043 } else {
4044 hdd_err("get station info cmd type failed");
4045 status = -EINVAL;
4046 goto out;
4047 }
4048 EXIT();
4049out:
4050 return status;
4051}
4052
4053/**
4054 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4055 * @wiphy: corestack handler
4056 * @wdev: wireless device
4057 * @data: data
4058 * @data_len: data length
4059 *
4060 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4061 * Validate cmd attributes and send the station info to upper layers.
4062 *
4063 * Return: Success(0) or reason code for failure
4064 */
4065static int32_t
4066hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4067 struct wireless_dev *wdev,
4068 const void *data,
4069 int data_len)
4070{
4071 int ret;
4072
4073 cds_ssr_protect(__func__);
4074 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
4075 cds_ssr_unprotect(__func__);
4076
4077 return ret;
4078}
4079
4080/*
4081 * undef short names defined for get station command
4082 * used by __wlan_hdd_cfg80211_get_station_cmd()
4083 */
4084#undef STATION_INVALID
4085#undef STATION_INFO
4086#undef STATION_ASSOC_FAIL_REASON
4087#undef STATION_MAX
4088
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004089#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4090/**
4091 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4092 * @wiphy: pointer to wireless wiphy structure.
4093 * @wdev: pointer to wireless_dev structure.
4094 * @data: Pointer to the Key data
4095 * @data_len:Length of the data passed
4096 *
4097 * This is called when wlan driver needs to save the keys received via
4098 * vendor specific command.
4099 *
4100 * Return: Return the Success or Failure code.
4101 */
4102static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4103 struct wireless_dev *wdev,
4104 const void *data, int data_len)
4105{
4106 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4107 struct net_device *dev = wdev->netdev;
4108 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4109 hdd_context_t *hdd_ctx_ptr;
4110 int status;
4111
Jeff Johnson1f61b612016-02-12 16:28:33 -08004112 ENTER_DEV(dev);
4113
Anurag Chouhan6d760662016-02-20 16:05:43 +05304114 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 hdd_err("Command not allowed in FTM mode");
4116 return -EPERM;
4117 }
4118
4119 if ((data == NULL) || (data_len == 0) ||
4120 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004121 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004122 return -EINVAL;
4123 }
4124
4125 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4126 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004127 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004128 return -EINVAL;
4129 }
4130
4131 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304132 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004133 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4135 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004136 true,
4137 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304138 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4139 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4141 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4142 return 0;
4143}
4144
4145/**
4146 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4147 * @wiphy: pointer to wireless wiphy structure.
4148 * @wdev: pointer to wireless_dev structure.
4149 * @data: Pointer to the Key data
4150 * @data_len:Length of the data passed
4151 *
4152 * This is called when wlan driver needs to save the keys received via
4153 * vendor specific command.
4154 *
4155 * Return: Return the Success or Failure code.
4156 */
4157static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4158 struct wireless_dev *wdev,
4159 const void *data, int data_len)
4160{
4161 int ret;
4162
4163 cds_ssr_protect(__func__);
4164 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4165 cds_ssr_unprotect(__func__);
4166
4167 return ret;
4168}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004169#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170
4171static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4172 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4173 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4174 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004175 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176};
4177
4178/**
4179 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4180 * @wiphy: pointer to wireless wiphy structure.
4181 * @wdev: pointer to wireless_dev structure.
4182 * @data: Pointer to the data to be passed via vendor interface
4183 * @data_len:Length of the data to be passed
4184 *
4185 * This is called when wlan driver needs to send wifi driver related info
4186 * (driver/fw version) to the user space application upon request.
4187 *
4188 * Return: Return the Success or Failure code.
4189 */
4190static int
4191__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4192 struct wireless_dev *wdev,
4193 const void *data, int data_len)
4194{
4195 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4196 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004197 tSirVersionString driver_version;
4198 tSirVersionString firmware_version;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004199 const char *hw_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004200 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004201 uint32_t sub_id = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004203 struct sk_buff *reply_skb;
4204 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004205
Jeff Johnson1f61b612016-02-12 16:28:33 -08004206 ENTER_DEV(wdev->netdev);
4207
Anurag Chouhan6d760662016-02-20 16:05:43 +05304208 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004209 hdd_err("Command not allowed in FTM mode");
4210 return -EPERM;
4211 }
4212
4213 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304214 if (status)
4215 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004216
4217 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4218 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004219 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004220 return -EINVAL;
4221 }
4222
4223 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004224 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004225 strlcpy(driver_version, QWLAN_VERSIONSTR,
4226 sizeof(driver_version));
4227 skb_len += strlen(driver_version) + 1;
4228 count++;
4229 }
4230
4231 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004232 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004233 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4234 &crmid);
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004235 sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
4236 hw_version = hdd_ctx->target_hw_name;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004237 snprintf(firmware_version, sizeof(firmware_version),
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004238 "FW:%d.%d.%d.%d.%d HW:%s", major_spid, minor_spid,
4239 siid, crmid, sub_id, hw_version);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004240 skb_len += strlen(firmware_version) + 1;
4241 count++;
4242 }
4243
4244 if (count == 0) {
4245 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004246 return -EINVAL;
4247 }
4248
Ryan Hsu7ac88852016-04-28 10:20:34 -07004249 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4250 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4251
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004252 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004253 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254 return -ENOMEM;
4255 }
4256
Ryan Hsu7ac88852016-04-28 10:20:34 -07004257 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4258 if (nla_put_string(reply_skb,
4259 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4260 driver_version))
4261 goto error_nla_fail;
4262 }
4263
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304264 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004265 if (nla_put_string(reply_skb,
4266 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4267 firmware_version))
4268 goto error_nla_fail;
4269 }
4270
4271 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4272 if (nla_put_u32(reply_skb,
4273 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4274 hdd_ctx->radio_index))
4275 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004276 }
4277
4278 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004279
4280error_nla_fail:
4281 hdd_err("nla put fail");
4282 kfree_skb(reply_skb);
4283 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284}
4285
4286/**
4287 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4288 * @wiphy: pointer to wireless wiphy structure.
4289 * @wdev: pointer to wireless_dev structure.
4290 * @data: Pointer to the data to be passed via vendor interface
4291 * @data_len:Length of the data to be passed
4292 *
4293 * This is called when wlan driver needs to send wifi driver related info
4294 * (driver/fw version) to the user space application upon request.
4295 *
4296 * Return: Return the Success or Failure code.
4297 */
4298static int
4299wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4300 struct wireless_dev *wdev,
4301 const void *data, int data_len)
4302{
4303 int ret;
4304
4305 cds_ssr_protect(__func__);
4306 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4307 cds_ssr_unprotect(__func__);
4308
4309 return ret;
4310}
4311
4312/**
4313 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4314 * @wiphy: pointer to wireless wiphy structure.
4315 * @wdev: pointer to wireless_dev structure.
4316 * @data: Pointer to the data to be passed via vendor interface
4317 * @data_len:Length of the data to be passed
4318 *
4319 * This is called by userspace to know the supported logger features
4320 *
4321 * Return: Return the Success or Failure code.
4322 */
4323static int
4324__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4325 struct wireless_dev *wdev,
4326 const void *data, int data_len)
4327{
4328 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4329 int status;
4330 uint32_t features;
4331 struct sk_buff *reply_skb = NULL;
4332
Jeff Johnson1f61b612016-02-12 16:28:33 -08004333 ENTER_DEV(wdev->netdev);
4334
Anurag Chouhan6d760662016-02-20 16:05:43 +05304335 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336 hdd_err("Command not allowed in FTM mode");
4337 return -EPERM;
4338 }
4339
4340 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304341 if (status)
4342 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004343
4344 features = 0;
4345
4346 if (hdd_is_memdump_supported())
4347 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4348 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4349 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4350 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4351
4352 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4353 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4354 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004355 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004356 return -ENOMEM;
4357 }
4358
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004359 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004360 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4361 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004362 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004363 kfree_skb(reply_skb);
4364 return -EINVAL;
4365 }
4366
4367 return cfg80211_vendor_cmd_reply(reply_skb);
4368}
4369
4370/**
4371 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4372 * @wiphy: pointer to wireless wiphy structure.
4373 * @wdev: pointer to wireless_dev structure.
4374 * @data: Pointer to the data to be passed via vendor interface
4375 * @data_len:Length of the data to be passed
4376 *
4377 * This is called by userspace to know the supported logger features
4378 *
4379 * Return: Return the Success or Failure code.
4380 */
4381static int
4382wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4383 struct wireless_dev *wdev,
4384 const void *data, int data_len)
4385{
4386 int ret;
4387
4388 cds_ssr_protect(__func__);
4389 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4390 data, data_len);
4391 cds_ssr_unprotect(__func__);
4392
4393 return ret;
4394}
4395
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004396#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004397/**
4398 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304399 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 * @bssid: pointer to bssid of roamed AP.
4401 * @req_rsn_ie: Pointer to request RSN IE
4402 * @req_rsn_len: Length of the request RSN IE
4403 * @rsp_rsn_ie: Pointer to response RSN IE
4404 * @rsp_rsn_len: Length of the response RSN IE
4405 * @roam_info_ptr: Pointer to the roaming related information
4406 *
4407 * This is called when wlan driver needs to send the roaming and
4408 * authorization information after roaming.
4409 *
4410 * The information that would be sent is the request RSN IE, response
4411 * RSN IE and BSSID of the newly roamed AP.
4412 *
4413 * If the Authorized status is authenticated, then additional parameters
4414 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4415 * supplicant.
4416 *
4417 * The supplicant upon receiving this event would ignore the legacy
4418 * cfg80211_roamed call and use the entire information from this event.
4419 * The cfg80211_roamed should still co-exist since the kernel will
4420 * make use of the parameters even if the supplicant ignores it.
4421 *
4422 * Return: Return the Success or Failure code.
4423 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304424int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004425 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4426 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4427{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304428 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004429 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004430 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004431 ENTER();
4432
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304433 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004434 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004435
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004436 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004437 !roam_info_ptr->roamSynchInProgress)
4438 return 0;
4439
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004440 /*
4441 * The user space has issued a disconnect when roaming is in
4442 * progress. The disconnect should be honored gracefully.
4443 * If the roaming is complete and the roam event is sent
4444 * back to the user space, it will get confused as it is
4445 * expecting a disconnect event. So, do not send the event
4446 * and handle the disconnect later.
4447 */
4448 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004449 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004450 return 0;
4451 }
4452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004453 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304454 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004455 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4456 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4457 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004458 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004459 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4460 GFP_KERNEL);
4461
4462 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004463 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004464 return -EINVAL;
4465 }
4466
4467 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4468 ETH_ALEN, bssid) ||
4469 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4470 req_rsn_len, req_rsn_ie) ||
4471 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4472 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004473 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004474 goto nla_put_failure;
4475 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476 if (roam_info_ptr->synchAuthStatus ==
4477 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004478 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004479 if (nla_put_u8(skb,
4480 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4481 hdd_err("nla put fail");
4482 goto nla_put_failure;
4483 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004484 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4485 /* if FT or CCKM connection: dont send replay counter */
4486 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4487 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4488 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4489 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4490 nla_put(skb,
4491 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4492 SIR_REPLAY_CTR_LEN,
4493 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004494 hdd_err("non FT/non CCKM connection");
4495 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004496 goto nla_put_failure;
4497 }
4498 if (nla_put(skb,
4499 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4500 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4501 nla_put(skb,
4502 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4503 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4504 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004505 goto nla_put_failure;
4506 }
4507 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004508 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4510 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004511 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004512 goto nla_put_failure;
4513 }
4514 }
4515
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304516 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4517 roam_info_ptr->synchAuthStatus,
4518 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004519
4520 /*
4521 * Add subnet change status if subnet has changed
4522 * 0 = unchanged
4523 * 1 = changed
4524 * 2 = unknown
4525 */
4526 if (roam_info_ptr->subnet_change_status) {
4527 if (nla_put_u8(skb,
4528 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4529 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004530 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004531 goto nla_put_failure;
4532 }
4533 }
4534
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004535 cfg80211_vendor_event(skb, GFP_KERNEL);
4536 return 0;
4537
4538nla_put_failure:
4539 kfree_skb(skb);
4540 return -EINVAL;
4541}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004542#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543
lifeng907edd62017-05-12 10:10:36 +08004544#define ANT_DIV_PROBE_PERIOD \
4545 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
4546#define ANT_DIV_STAY_PERIOD \
4547 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
4548#define ANT_DIV_SNR_DIFF \
4549 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
4550#define ANT_DIV_PROBE_DWELL_TIME \
4551 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
4552#define ANT_DIV_MGMT_SNR_WEIGHT \
4553 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
4554#define ANT_DIV_DATA_SNR_WEIGHT \
4555 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
4556#define ANT_DIV_ACK_SNR_WEIGHT \
4557 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004558static const struct nla_policy
4559wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4560
4561 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4562 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4563 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304564 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304565 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4566 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004567 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4568 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4569 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4570 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4571 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304572 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08004573 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
4574 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
4575 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
4576 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
4577 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
4578 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
4579 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580};
4581
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004582/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304583 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4584 *
4585 * @adapter: Pointer to HDD adapter
4586 * @ie_data: Pointer to Scan IEs buffer
4587 * @ie_len: Length of Scan IEs
4588 *
4589 * Return: 0 on success; error number otherwise
4590 */
4591static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4592 uint8_t *ie_data, uint8_t ie_len)
4593{
4594 hdd_scaninfo_t *scan_info = NULL;
4595 scan_info = &adapter->scan_info;
4596
4597 if (scan_info->default_scan_ies) {
4598 qdf_mem_free(scan_info->default_scan_ies);
4599 scan_info->default_scan_ies = NULL;
4600 }
4601
4602 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4603 if (!scan_info->default_scan_ies)
4604 return -ENOMEM;
4605
4606 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4607 scan_info->default_scan_ies_len = ie_len;
4608 return 0;
4609}
4610
4611/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004612 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4613 * vendor command
4614 *
4615 * @wiphy: wiphy device pointer
4616 * @wdev: wireless device pointer
4617 * @data: Vendor command data buffer
4618 * @data_len: Buffer length
4619 *
4620 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4621 *
4622 * Return: Error code.
4623 */
4624static int
4625__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4626 struct wireless_dev *wdev,
4627 const void *data,
4628 int data_len)
4629{
4630 struct net_device *dev = wdev->netdev;
4631 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4632 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4633 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4634 int ret_val = 0;
4635 u32 modulated_dtim;
4636 u16 stats_avg_factor;
4637 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304638 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004639 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004640 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304641 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304642 int attr_len;
4643 int access_policy = 0;
4644 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4645 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304646 uint16_t scan_ie_len = 0;
4647 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304648 struct sir_set_tx_rx_aggregation_size request;
4649 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004650 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004651 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004652 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304653 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08004654 uint32_t ant_div_usrcfg;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304655
Jeff Johnson1f61b612016-02-12 16:28:33 -08004656 ENTER_DEV(dev);
4657
Anurag Chouhan6d760662016-02-20 16:05:43 +05304658 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004659 hdd_err("Command not allowed in FTM mode");
4660 return -EPERM;
4661 }
4662
4663 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304664 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004666
4667 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4668 data, data_len,
4669 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004670 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004671 return -EINVAL;
4672 }
4673
Krunal Sonie3531942016-04-12 17:43:53 -07004674 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4675 ftm_capab = nla_get_u32(tb[
4676 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4677 hdd_ctx->config->fine_time_meas_cap =
4678 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4679 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304680 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004681 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004682 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4683 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004684 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004685 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4686 hdd_ctx->config->fine_time_meas_cap);
4687 }
4688
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4690 modulated_dtim = nla_get_u32(
4691 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4692
4693 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4694 adapter->sessionId,
4695 modulated_dtim);
4696
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304697 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004698 ret_val = -EPERM;
4699 }
4700
Kapil Gupta6213c012016-09-02 19:39:09 +05304701 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4702 qpower = nla_get_u8(
4703 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4704 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4705 ret_val = -EINVAL;
4706 }
4707
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004708 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4709 stats_avg_factor = nla_get_u16(
4710 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4711 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4712 adapter->sessionId,
4713 stats_avg_factor);
4714
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304715 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004716 ret_val = -EPERM;
4717 }
4718
4719
4720 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4721 guard_time = nla_get_u32(
4722 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4723 status = sme_configure_guard_time(hdd_ctx->hHal,
4724 adapter->sessionId,
4725 guard_time);
4726
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304727 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004728 ret_val = -EPERM;
4729 }
4730
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304731 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4732 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4733 attr_len = nla_len(
4734 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4735 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004736 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304737 attr_len);
4738 return -EINVAL;
4739 }
4740
4741 nla_memcpy(&vendor_ie,
4742 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4743 attr_len);
4744 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004745 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304746 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304747 }
4748
4749 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4750 access_policy = (int) nla_get_u32(
4751 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4752 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4753 (access_policy >
4754 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004755 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304756 access_policy);
4757 return -EINVAL;
4758 }
4759 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004760 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304761 access_policy);
4762 }
4763
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004764 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4765 retry = nla_get_u8(tb[
4766 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4767 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4768 CFG_NON_AGG_RETRY_MAX : retry;
4769 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4770 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4771 retry, PDEV_CMD);
4772 }
4773
4774 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4775 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4776 retry = retry > CFG_AGG_RETRY_MAX ?
4777 CFG_AGG_RETRY_MAX : retry;
4778
4779 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4780 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4781 CFG_AGG_RETRY_MIN : retry;
4782 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4783 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4784 retry, PDEV_CMD);
4785 }
4786
4787 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4788 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4789 retry = retry > CFG_MGMT_RETRY_MAX ?
4790 CFG_MGMT_RETRY_MAX : retry;
4791 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4792 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4793 retry, PDEV_CMD);
4794 }
4795
4796 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4797 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4798 retry = retry > CFG_CTRL_RETRY_MAX ?
4799 CFG_CTRL_RETRY_MAX : retry;
4800 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4801 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4802 retry, PDEV_CMD);
4803 }
4804
4805 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4806 delay = nla_get_u8(tb[
4807 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4808 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4809 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004810 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004811 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4812 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004813 abs_delay, PDEV_CMD);
4814 }
4815
4816 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4817 abs_delay = nla_get_u8(tb[
4818 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4819 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4820 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4821 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004822 }
4823
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304824 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4825 tx_fail_count = nla_get_u32(
4826 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4827 if (tx_fail_count) {
4828 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4829 adapter->sessionId, tx_fail_count);
4830 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004831 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304832 status);
4833 return -EINVAL;
4834 }
4835 }
4836 }
4837
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304838 if (vendor_ie_present && access_policy_present) {
4839 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4840 access_policy =
4841 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304842 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304843 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304844 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304845
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004846 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304847 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4848 adapter->sessionId, &vendor_ie[0],
4849 access_policy);
4850 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004851 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304852 return -EINVAL;
4853 }
4854 }
4855
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304856 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4857 set_value = nla_get_u8(
4858 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004859 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304860 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4861 }
4862
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304863 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4864 scan_ie_len = nla_len(
4865 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004866 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304867 scan_ie_len, adapter->sessionId,
4868 adapter->device_mode);
4869 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4870 scan_ie = (uint8_t *) nla_data(tb
4871 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304872
4873 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4874 scan_ie_len))
4875 hdd_err("Failed to save default scan IEs");
4876
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304877 if (adapter->device_mode == QDF_STA_MODE) {
4878 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4879 adapter->sessionId, scan_ie,
4880 scan_ie_len);
4881 if (QDF_STATUS_SUCCESS != status)
4882 ret_val = -EPERM;
4883 }
4884 } else
4885 ret_val = -EPERM;
4886 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304887
4888 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4889 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4890 /* if one is specified, both must be specified */
4891 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4892 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4893 hdd_err("Both TX and RX MPDU Aggregation required");
4894 return -EINVAL;
4895 }
4896
4897 request.tx_aggregation_size = nla_get_u8(
4898 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4899 request.rx_aggregation_size = nla_get_u8(
4900 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4901 request.vdev_id = adapter->sessionId;
4902
4903 if (request.tx_aggregation_size >=
4904 CFG_TX_AGGREGATION_SIZE_MIN &&
4905 request.tx_aggregation_size <=
4906 CFG_TX_AGGREGATION_SIZE_MAX &&
4907 request.rx_aggregation_size >=
4908 CFG_RX_AGGREGATION_SIZE_MIN &&
4909 request.rx_aggregation_size <=
4910 CFG_RX_AGGREGATION_SIZE_MAX) {
4911 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4912 if (qdf_status != QDF_STATUS_SUCCESS) {
4913 hdd_err("failed to set aggr sizes err %d",
4914 qdf_status);
4915 ret_val = -EPERM;
4916 }
4917 } else {
4918 hdd_err("TX %d RX %d MPDU aggr size not in range",
4919 request.tx_aggregation_size,
4920 request.rx_aggregation_size);
4921 ret_val = -EINVAL;
4922 }
4923 }
4924
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304925 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4926 uint8_t ignore_assoc_disallowed;
4927
4928 ignore_assoc_disallowed
4929 = nla_get_u8(tb[
4930 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004931 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304932 ignore_assoc_disallowed);
4933 if ((ignore_assoc_disallowed <
4934 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4935 (ignore_assoc_disallowed >
4936 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4937 return -EPERM;
4938
4939 sme_update_session_param(hdd_ctx->hHal,
4940 adapter->sessionId,
4941 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4942 ignore_assoc_disallowed);
4943 }
4944
lifeng907edd62017-05-12 10:10:36 +08004945#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
4946 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
4947
4948#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
4949 ((1<<27)|(snr_diff&0x1fff))
4950
4951#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
4952 ((1<<28)|(probe_dwell_time&0x1fff))
4953
4954#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
4955 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
4956 (ack_snr_weight&0xff))
4957
4958 if (tb[ANT_DIV_PROBE_PERIOD] ||
4959 tb[ANT_DIV_STAY_PERIOD]) {
4960
4961 if (!tb[ANT_DIV_PROBE_PERIOD] ||
4962 !tb[ANT_DIV_STAY_PERIOD]) {
4963 hdd_err("Both probe and stay period required");
4964 return -EINVAL;
4965 }
4966
4967 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
4968 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
4969 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
4970 hdd_debug("ant div set period: %x", ant_div_usrcfg);
4971 ret_val = wma_cli_set_command((int)adapter->sessionId,
4972 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
4973 ant_div_usrcfg, PDEV_CMD);
4974 if (ret_val) {
4975 hdd_err("Failed to set ant div period");
4976 return ret_val;
4977 }
4978 }
4979
4980 if (tb[ANT_DIV_SNR_DIFF]) {
4981 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
4982 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
4983 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
4984 ret_val = wma_cli_set_command((int)adapter->sessionId,
4985 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
4986 ant_div_usrcfg, PDEV_CMD);
4987 if (ret_val) {
4988 hdd_err("Failed to set ant snr diff");
4989 return ret_val;
4990 }
4991 }
4992
4993 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
4994 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
4995 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
4996 hdd_debug("ant div set probe dewll time: %x",
4997 ant_div_usrcfg);
4998 ret_val = wma_cli_set_command((int)adapter->sessionId,
4999 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5000 ant_div_usrcfg, PDEV_CMD);
5001 if (ret_val) {
5002 hdd_err("Failed to set ant div probe dewll time");
5003 return ret_val;
5004 }
5005 }
5006
5007 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5008 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5009 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5010
5011 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5012 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5013 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5014 hdd_err("Mgmt snr, data snr and ack snr weight are required");
5015 return -EINVAL;
5016 }
5017
5018 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
5019 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
5020 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
5021 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
5022 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
5023 ret_val = wma_cli_set_command((int)adapter->sessionId,
5024 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5025 ant_div_usrcfg, PDEV_CMD);
5026 if (ret_val) {
5027 hdd_err("Failed to set ant div weight");
5028 return ret_val;
5029 }
5030 }
5031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005032 return ret_val;
5033}
5034
5035/**
5036 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
5037 * vendor command
5038 *
5039 * @wiphy: wiphy device pointer
5040 * @wdev: wireless device pointer
5041 * @data: Vendor command data buffer
5042 * @data_len: Buffer length
5043 *
5044 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
5045 *
5046 * Return: EOK or other error codes.
5047 */
5048static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
5049 struct wireless_dev *wdev,
5050 const void *data,
5051 int data_len)
5052{
5053 int ret;
5054
5055 cds_ssr_protect(__func__);
5056 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
5057 data, data_len);
5058 cds_ssr_unprotect(__func__);
5059
5060 return ret;
5061}
5062
5063static const struct
5064nla_policy
5065qca_wlan_vendor_wifi_logger_start_policy
5066[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
5067 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
5068 = {.type = NLA_U32 },
5069 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
5070 = {.type = NLA_U32 },
5071 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
5072 = {.type = NLA_U32 },
5073};
5074
5075/**
5076 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
5077 * or disable the collection of packet statistics from the firmware
5078 * @wiphy: WIPHY structure pointer
5079 * @wdev: Wireless device structure pointer
5080 * @data: Pointer to the data received
5081 * @data_len: Length of the data received
5082 *
5083 * This function enables or disables the collection of packet statistics from
5084 * the firmware
5085 *
5086 * Return: 0 on success and errno on failure
5087 */
5088static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5089 struct wireless_dev *wdev,
5090 const void *data,
5091 int data_len)
5092{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305093 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005094 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5095 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
5096 struct sir_wifi_start_log start_log;
5097
Jeff Johnson1f61b612016-02-12 16:28:33 -08005098 ENTER_DEV(wdev->netdev);
5099
Anurag Chouhan6d760662016-02-20 16:05:43 +05305100 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005101 hdd_err("Command not allowed in FTM mode");
5102 return -EPERM;
5103 }
5104
5105 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305106 if (status)
5107 return status;
5108
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05305109 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
5110 hdd_err("Driver Modules are closed, can not start logger");
5111 return -EINVAL;
5112 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005113
5114 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
5115 data, data_len,
5116 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005117 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005118 return -EINVAL;
5119 }
5120
5121 /* Parse and fetch ring id */
5122 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005123 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005124 return -EINVAL;
5125 }
5126 start_log.ring_id = nla_get_u32(
5127 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005128 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005129
5130 /* Parse and fetch verbose level */
5131 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005132 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005133 return -EINVAL;
5134 }
5135 start_log.verbose_level = nla_get_u32(
5136 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005137 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005138
5139 /* Parse and fetch flag */
5140 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005141 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142 return -EINVAL;
5143 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05305144 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005145 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005146 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005147
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305148 /* size is buff size which can be set using iwpriv command*/
5149 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05305150 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005152 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
5153
5154 if (start_log.ring_id == RING_ID_WAKELOCK) {
5155 /* Start/stop wakelock events */
5156 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
5157 cds_set_wakelock_logging(true);
5158 else
5159 cds_set_wakelock_logging(false);
5160 return 0;
5161 }
5162
5163 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305164 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005165 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166 status);
5167 return -EINVAL;
5168 }
5169 return 0;
5170}
5171
5172/**
5173 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
5174 * or disable the collection of packet statistics from the firmware
5175 * @wiphy: WIPHY structure pointer
5176 * @wdev: Wireless device structure pointer
5177 * @data: Pointer to the data received
5178 * @data_len: Length of the data received
5179 *
5180 * This function is used to enable or disable the collection of packet
5181 * statistics from the firmware
5182 *
5183 * Return: 0 on success and errno on failure
5184 */
5185static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5186 struct wireless_dev *wdev,
5187 const void *data,
5188 int data_len)
5189{
5190 int ret = 0;
5191
5192 cds_ssr_protect(__func__);
5193 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5194 wdev, data, data_len);
5195 cds_ssr_unprotect(__func__);
5196
5197 return ret;
5198}
5199
5200static const struct
5201nla_policy
5202qca_wlan_vendor_wifi_logger_get_ring_data_policy
5203[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5204 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5205 = {.type = NLA_U32 },
5206};
5207
5208/**
5209 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5210 * @wiphy: WIPHY structure pointer
5211 * @wdev: Wireless device structure pointer
5212 * @data: Pointer to the data received
5213 * @data_len: Length of the data received
5214 *
5215 * This function is used to flush or retrieve the per packet statistics from
5216 * the driver
5217 *
5218 * Return: 0 on success and errno on failure
5219 */
5220static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5221 struct wireless_dev *wdev,
5222 const void *data,
5223 int data_len)
5224{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305225 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 uint32_t ring_id;
5227 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5228 struct nlattr *tb
5229 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5230
Jeff Johnson1f61b612016-02-12 16:28:33 -08005231 ENTER_DEV(wdev->netdev);
5232
Anurag Chouhan6d760662016-02-20 16:05:43 +05305233 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 hdd_err("Command not allowed in FTM mode");
5235 return -EPERM;
5236 }
5237
5238 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305239 if (status)
5240 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241
5242 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5243 data, data_len,
5244 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005245 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005246 return -EINVAL;
5247 }
5248
5249 /* Parse and fetch ring id */
5250 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005251 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 return -EINVAL;
5253 }
5254
5255 ring_id = nla_get_u32(
5256 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5257
5258 if (ring_id == RING_ID_PER_PACKET_STATS) {
5259 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005260 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305261 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5262 /*
5263 * As part of DRIVER ring ID, flush both driver and fw logs.
5264 * For other Ring ID's driver doesn't have any rings to flush
5265 */
5266 hdd_notice("Bug report triggered by framework");
5267
5268 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5269 WLAN_LOG_INDICATOR_FRAMEWORK,
5270 WLAN_LOG_REASON_CODE_UNUSED,
5271 true, false);
5272 if (QDF_STATUS_SUCCESS != status) {
5273 hdd_err("Failed to trigger bug report");
5274 return -EINVAL;
5275 }
5276 } else {
5277 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5278 WLAN_LOG_INDICATOR_FRAMEWORK,
5279 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005281 return 0;
5282}
5283
5284/**
5285 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5286 * @wiphy: WIPHY structure pointer
5287 * @wdev: Wireless device structure pointer
5288 * @data: Pointer to the data received
5289 * @data_len: Length of the data received
5290 *
5291 * This function is used to flush or retrieve the per packet statistics from
5292 * the driver
5293 *
5294 * Return: 0 on success and errno on failure
5295 */
5296static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5297 struct wireless_dev *wdev,
5298 const void *data,
5299 int data_len)
5300{
5301 int ret = 0;
5302
5303 cds_ssr_protect(__func__);
5304 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5305 wdev, data, data_len);
5306 cds_ssr_unprotect(__func__);
5307
5308 return ret;
5309}
5310
5311#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5312/**
5313 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5314 * @hdd_ctx: HDD context
5315 * @request_id: [input] request id
5316 * @pattern_id: [output] pattern id
5317 *
5318 * This function loops through request id to pattern id array
5319 * if the slot is available, store the request id and return pattern id
5320 * if entry exists, return the pattern id
5321 *
5322 * Return: 0 on success and errno on failure
5323 */
5324static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5325 uint32_t request_id,
5326 uint8_t *pattern_id)
5327{
5328 uint32_t i;
5329
5330 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5331 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5332 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5333 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5334 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5335 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5336 return 0;
5337 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5338 request_id) {
5339 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5340 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5341 return 0;
5342 }
5343 }
5344 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5345 return -EINVAL;
5346}
5347
5348/**
5349 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5350 * @hdd_ctx: HDD context
5351 * @request_id: [input] request id
5352 * @pattern_id: [output] pattern id
5353 *
5354 * This function loops through request id to pattern id array
5355 * reset request id to 0 (slot available again) and
5356 * return pattern id
5357 *
5358 * Return: 0 on success and errno on failure
5359 */
5360static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5361 uint32_t request_id,
5362 uint8_t *pattern_id)
5363{
5364 uint32_t i;
5365
5366 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5367 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5368 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5369 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5370 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5371 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5372 return 0;
5373 }
5374 }
5375 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5376 return -EINVAL;
5377}
5378
5379
5380/*
5381 * define short names for the global vendor params
5382 * used by __wlan_hdd_cfg80211_offloaded_packets()
5383 */
5384#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5385#define PARAM_REQUEST_ID \
5386 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5387#define PARAM_CONTROL \
5388 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5389#define PARAM_IP_PACKET \
5390 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5391#define PARAM_SRC_MAC_ADDR \
5392 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5393#define PARAM_DST_MAC_ADDR \
5394 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5395#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5396
5397/**
5398 * wlan_hdd_add_tx_ptrn() - add tx pattern
5399 * @adapter: adapter pointer
5400 * @hdd_ctx: hdd context
5401 * @tb: nl attributes
5402 *
5403 * This function reads the NL attributes and forms a AddTxPtrn message
5404 * posts it to SME.
5405 *
5406 */
5407static int
5408wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5409 struct nlattr **tb)
5410{
5411 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305412 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 uint32_t request_id, ret, len;
5414 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305415 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416 uint16_t eth_type = htons(ETH_P_IP);
5417
5418 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005419 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005420 return -ENOTSUPP;
5421 }
5422
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305423 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005424 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005425 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 return -ENOMEM;
5427 }
5428
5429 /* Parse and fetch request Id */
5430 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005431 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005432 goto fail;
5433 }
5434
5435 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5436 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005437 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438 return -EINVAL;
5439 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005440 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005441
5442 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005443 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005444 goto fail;
5445 }
5446 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005447 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005448 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005449 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005450 goto fail;
5451 }
5452
5453 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005454 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005455 goto fail;
5456 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005457 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305458 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005459 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005460 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005461
Anurag Chouhanc5548422016-02-24 18:33:27 +05305462 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005463 &adapter->macAddressCurrent)) {
5464 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005465 goto fail;
5466 }
5467
5468 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005469 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005470 goto fail;
5471 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305472 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005473 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005474 MAC_ADDR_ARRAY(dst_addr.bytes));
5475
5476 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005477 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005478 goto fail;
5479 }
5480 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005481 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005482
5483 if (add_req->ucPtrnSize < 0 ||
5484 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5485 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005486 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487 add_req->ucPtrnSize);
5488 goto fail;
5489 }
5490
5491 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305492 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305493 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305494 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305495 QDF_MAC_ADDR_SIZE);
5496 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305497 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005498 len += 2;
5499
5500 /*
5501 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5502 * ------------------------------------------------------------
5503 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5504 * ------------------------------------------------------------
5505 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305506 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005507 nla_data(tb[PARAM_IP_PACKET]),
5508 add_req->ucPtrnSize);
5509 add_req->ucPtrnSize += len;
5510
5511 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5512 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005513 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005514 goto fail;
5515 }
5516 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005517 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005518
5519 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305520 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005521 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522 goto fail;
5523 }
5524
5525 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305526 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005527 return 0;
5528
5529fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305530 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531 return -EINVAL;
5532}
5533
5534/**
5535 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5536 * @adapter: adapter pointer
5537 * @hdd_ctx: hdd context
5538 * @tb: nl attributes
5539 *
5540 * This function reads the NL attributes and forms a DelTxPtrn message
5541 * posts it to SME.
5542 *
5543 */
5544static int
5545wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5546 struct nlattr **tb)
5547{
5548 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305549 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550 uint32_t request_id, ret;
5551 uint8_t pattern_id = 0;
5552
5553 /* Parse and fetch request Id */
5554 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005555 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005556 return -EINVAL;
5557 }
5558 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5559 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005560 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005561 return -EINVAL;
5562 }
5563
5564 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5565 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005566 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005567 return -EINVAL;
5568 }
5569
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305570 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005572 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005573 return -ENOMEM;
5574 }
5575
Anurag Chouhanc5548422016-02-24 18:33:27 +05305576 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005577 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005578 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005579 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005580 request_id, del_req->ucPtrnId);
5581
5582 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305583 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005584 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005585 goto fail;
5586 }
5587
5588 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305589 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590 return 0;
5591
5592fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305593 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005594 return -EINVAL;
5595}
5596
5597
5598/**
5599 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5600 * @wiphy: Pointer to wireless phy
5601 * @wdev: Pointer to wireless device
5602 * @data: Pointer to data
5603 * @data_len: Data length
5604 *
5605 * Return: 0 on success, negative errno on failure
5606 */
5607static int
5608__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5609 struct wireless_dev *wdev,
5610 const void *data,
5611 int data_len)
5612{
5613 struct net_device *dev = wdev->netdev;
5614 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5615 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5616 struct nlattr *tb[PARAM_MAX + 1];
5617 uint8_t control;
5618 int ret;
5619 static const struct nla_policy policy[PARAM_MAX + 1] = {
5620 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5621 [PARAM_CONTROL] = { .type = NLA_U32 },
5622 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305623 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005624 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305625 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005626 [PARAM_PERIOD] = { .type = NLA_U32 },
5627 };
5628
Jeff Johnson1f61b612016-02-12 16:28:33 -08005629 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005630
Anurag Chouhan6d760662016-02-20 16:05:43 +05305631 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632 hdd_err("Command not allowed in FTM mode");
5633 return -EPERM;
5634 }
5635
5636 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305637 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005638 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005639
5640 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005641 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005642 return -ENOTSUPP;
5643 }
5644
5645 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005646 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005647 return -EINVAL;
5648 }
5649
5650 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005651 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652 return -EINVAL;
5653 }
5654 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005655 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005656
5657 if (control == WLAN_START_OFFLOADED_PACKETS)
5658 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005659 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005661
5662 hdd_err("Invalid control: %d", control);
5663
5664 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665}
5666
5667/*
5668 * done with short names for the global vendor params
5669 * used by __wlan_hdd_cfg80211_offloaded_packets()
5670 */
5671#undef PARAM_MAX
5672#undef PARAM_REQUEST_ID
5673#undef PARAM_CONTROL
5674#undef PARAM_IP_PACKET
5675#undef PARAM_SRC_MAC_ADDR
5676#undef PARAM_DST_MAC_ADDR
5677#undef PARAM_PERIOD
5678
5679/**
5680 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5681 * @wiphy: wiphy structure pointer
5682 * @wdev: Wireless device structure pointer
5683 * @data: Pointer to the data received
5684 * @data_len: Length of @data
5685 *
5686 * Return: 0 on success; errno on failure
5687 */
5688static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5689 struct wireless_dev *wdev,
5690 const void *data,
5691 int data_len)
5692{
5693 int ret = 0;
5694
5695 cds_ssr_protect(__func__);
5696 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5697 wdev, data, data_len);
5698 cds_ssr_unprotect(__func__);
5699
5700 return ret;
5701}
5702#endif
5703
5704/*
5705 * define short names for the global vendor params
5706 * used by __wlan_hdd_cfg80211_monitor_rssi()
5707 */
5708#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5709#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5710#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5711#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5712#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5713
5714/**
5715 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5716 * @wiphy: Pointer to wireless phy
5717 * @wdev: Pointer to wireless device
5718 * @data: Pointer to data
5719 * @data_len: Data length
5720 *
5721 * Return: 0 on success, negative errno on failure
5722 */
5723static int
5724__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5725 struct wireless_dev *wdev,
5726 const void *data,
5727 int data_len)
5728{
5729 struct net_device *dev = wdev->netdev;
5730 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5731 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5732 struct nlattr *tb[PARAM_MAX + 1];
5733 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305734 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735 int ret;
5736 uint32_t control;
5737 static const struct nla_policy policy[PARAM_MAX + 1] = {
5738 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5739 [PARAM_CONTROL] = { .type = NLA_U32 },
5740 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5741 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5742 };
5743
Jeff Johnson1f61b612016-02-12 16:28:33 -08005744 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005745
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305746 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5747 hdd_err("invalid session id: %d", adapter->sessionId);
5748 return -EINVAL;
5749 }
5750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005751 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305752 if (ret)
5753 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754
5755 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005756 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005757 return -ENOTSUPP;
5758 }
5759
5760 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005761 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005762 return -EINVAL;
5763 }
5764
5765 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005766 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005767 return -EINVAL;
5768 }
5769
5770 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005771 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005772 return -EINVAL;
5773 }
5774
5775 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5776 req.session_id = adapter->sessionId;
5777 control = nla_get_u32(tb[PARAM_CONTROL]);
5778
5779 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5780 req.control = true;
5781 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005782 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005783 return -EINVAL;
5784 }
5785
5786 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005787 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005788 return -EINVAL;
5789 }
5790
5791 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5792 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5793
5794 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005795 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796 req.min_rssi, req.max_rssi);
5797 return -EINVAL;
5798 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005799 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005800 req.min_rssi, req.max_rssi);
5801
5802 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5803 req.control = false;
5804 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005805 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005806 return -EINVAL;
5807 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005808 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809 req.request_id, req.session_id, req.control);
5810
5811 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305812 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005813 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005814 return -EINVAL;
5815 }
5816
5817 return 0;
5818}
5819
5820/*
5821 * done with short names for the global vendor params
5822 * used by __wlan_hdd_cfg80211_monitor_rssi()
5823 */
5824#undef PARAM_MAX
5825#undef PARAM_CONTROL
5826#undef PARAM_REQUEST_ID
5827#undef PARAM_MAX_RSSI
5828#undef PARAM_MIN_RSSI
5829
5830/**
5831 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5832 * @wiphy: wiphy structure pointer
5833 * @wdev: Wireless device structure pointer
5834 * @data: Pointer to the data received
5835 * @data_len: Length of @data
5836 *
5837 * Return: 0 on success; errno on failure
5838 */
5839static int
5840wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5841 const void *data, int data_len)
5842{
5843 int ret;
5844
5845 cds_ssr_protect(__func__);
5846 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5847 cds_ssr_unprotect(__func__);
5848
5849 return ret;
5850}
5851
5852/**
5853 * hdd_rssi_threshold_breached() - rssi breached NL event
5854 * @hddctx: HDD context
5855 * @data: rssi breached event data
5856 *
5857 * This function reads the rssi breached event %data and fill in the skb with
5858 * NL attributes and send up the NL event.
5859 *
5860 * Return: none
5861 */
5862void hdd_rssi_threshold_breached(void *hddctx,
5863 struct rssi_breach_event *data)
5864{
5865 hdd_context_t *hdd_ctx = hddctx;
5866 struct sk_buff *skb;
5867
5868 ENTER();
5869
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305870 if (wlan_hdd_validate_context(hdd_ctx))
5871 return;
5872 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005873 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005874 return;
5875 }
5876
5877 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5878 NULL,
5879 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5880 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5881 GFP_KERNEL);
5882
5883 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005884 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885 return;
5886 }
5887
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005888 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005889 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005890 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005891 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5892
5893 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5894 data->request_id) ||
5895 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5896 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5897 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5898 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005899 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005900 goto fail;
5901 }
5902
5903 cfg80211_vendor_event(skb, GFP_KERNEL);
5904 return;
5905
5906fail:
5907 kfree_skb(skb);
5908 return;
5909}
5910
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305911static const struct nla_policy
5912ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5913 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5914};
5915
5916/**
5917 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5918 * @wiphy: Pointer to wireless phy
5919 * @wdev: Pointer to wireless device
5920 * @data: Pointer to data
5921 * @data_len: Length of @data
5922 *
5923 * Return: 0 on success, negative errno on failure
5924 */
5925static int
5926__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5927 struct wireless_dev *wdev,
5928 const void *data, int data_len)
5929{
5930 int status;
5931 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5932 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005933 struct net_device *dev = wdev->netdev;
5934 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305935
5936 ENTER_DEV(wdev->netdev);
5937
5938 status = wlan_hdd_validate_context(pHddCtx);
5939 if (0 != status)
5940 return status;
5941 if (!pHddCtx->config->fhostNSOffload) {
5942 hdd_err("ND Offload not supported");
5943 return -EINVAL;
5944 }
5945
5946 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5947 (struct nlattr *)data,
5948 data_len, ns_offload_set_policy)) {
5949 hdd_err("nla_parse failed");
5950 return -EINVAL;
5951 }
5952
5953 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5954 hdd_err("ND Offload flag attribute not present");
5955 return -EINVAL;
5956 }
5957
5958 pHddCtx->ns_offload_enable =
5959 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5960
Dustin Brownd8279d22016-09-07 14:52:57 -07005961 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305962 if (pHddCtx->ns_offload_enable)
5963 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5964 else
5965 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005966
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305967 return 0;
5968}
5969
5970/**
5971 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5972 * @wiphy: pointer to wireless wiphy structure.
5973 * @wdev: pointer to wireless_dev structure.
5974 * @data: Pointer to the data to be passed via vendor interface
5975 * @data_len:Length of the data to be passed
5976 *
5977 * Return: Return the Success or Failure code.
5978 */
5979static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5980 struct wireless_dev *wdev,
5981 const void *data, int data_len)
5982{
5983 int ret;
5984
5985 cds_ssr_protect(__func__);
5986 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5987 cds_ssr_unprotect(__func__);
5988
5989 return ret;
5990}
5991
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005992/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5993 * @wiphy: Pointer to wireless phy
5994 * @wdev: Pointer to wireless device
5995 * @data: Pointer to data
5996 * @data_len: Data length
5997 *
5998 * This function return the preferred frequency list generated by the policy
5999 * manager.
6000 *
6001 * Return: success or failure code
6002 */
6003static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6004 struct wireless_dev
6005 *wdev, const void *data,
6006 int data_len)
6007{
6008 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6009 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306010 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306011 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006012 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306013 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006014 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6016 struct sk_buff *reply_skb;
6017
Jeff Johnson1f61b612016-02-12 16:28:33 -08006018 ENTER_DEV(wdev->netdev);
6019
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006020 ret = wlan_hdd_validate_context(hdd_ctx);
6021 if (ret)
6022 return -EINVAL;
6023
6024 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
6025 data, data_len, NULL)) {
6026 hdd_err("Invalid ATTR");
6027 return -EINVAL;
6028 }
6029
6030 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
6031 hdd_err("attr interface type failed");
6032 return -EINVAL;
6033 }
6034
6035 intf_mode = nla_get_u32(tb
6036 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
6037
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006038 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006039 hdd_err("Invalid interface type");
6040 return -EINVAL;
6041 }
6042
6043 hdd_debug("Userspace requested pref freq list");
6044
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006045 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
6046 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05306047 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306048 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006049 hdd_err("Get pcl failed");
6050 return -EINVAL;
6051 }
6052
6053 /* convert channel number to frequency */
6054 for (i = 0; i < pcl_len; i++) {
6055 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
6056 freq_list[i] =
6057 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006058 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006059 else
6060 freq_list[i] =
6061 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006062 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006063 }
6064
6065 /* send the freq_list back to supplicant */
6066 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
6067 sizeof(u32) *
6068 pcl_len +
6069 NLMSG_HDRLEN);
6070
6071 if (!reply_skb) {
6072 hdd_err("Allocate reply_skb failed");
6073 return -EINVAL;
6074 }
6075
6076 if (nla_put_u32(reply_skb,
6077 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
6078 intf_mode) ||
6079 nla_put(reply_skb,
6080 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
6081 sizeof(uint32_t) * pcl_len,
6082 freq_list)) {
6083 hdd_err("nla put fail");
6084 kfree_skb(reply_skb);
6085 return -EINVAL;
6086 }
6087
6088 return cfg80211_vendor_cmd_reply(reply_skb);
6089}
6090
6091/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
6092 * @wiphy: Pointer to wireless phy
6093 * @wdev: Pointer to wireless device
6094 * @data: Pointer to data
6095 * @data_len: Data length
6096 *
6097 * This function return the preferred frequency list generated by the policy
6098 * manager.
6099 *
6100 * Return: success or failure code
6101 */
6102static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6103 struct wireless_dev
6104 *wdev, const void *data,
6105 int data_len)
6106{
6107 int ret = 0;
6108
6109 cds_ssr_protect(__func__);
6110 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
6111 data, data_len);
6112 cds_ssr_unprotect(__func__);
6113
6114 return ret;
6115}
6116
6117/**
6118 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6119 * @wiphy: Pointer to wireless phy
6120 * @wdev: Pointer to wireless device
6121 * @data: Pointer to data
6122 * @data_len: Data length
6123 *
6124 * Return: 0 on success, negative errno on failure
6125 */
6126static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6127 struct wireless_dev *wdev,
6128 const void *data,
6129 int data_len)
6130{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05306131 struct net_device *ndev = wdev->netdev;
6132 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006133 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6134 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006135 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006136 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6137 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006138
Jeff Johnson1f61b612016-02-12 16:28:33 -08006139 ENTER_DEV(ndev);
6140
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006141 ret = wlan_hdd_validate_context(hdd_ctx);
6142 if (ret)
6143 return ret;
6144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006145 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
6146 data, data_len, NULL)) {
6147 hdd_err("Invalid ATTR");
6148 return -EINVAL;
6149 }
6150
6151 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
6152 hdd_err("attr interface type failed");
6153 return -EINVAL;
6154 }
6155
6156 intf_mode = nla_get_u32(tb
6157 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
6158
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006159 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006160 hdd_err("Invalid interface type");
6161 return -EINVAL;
6162 }
6163
6164 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
6165 hdd_err("attr probable freq failed");
6166 return -EINVAL;
6167 }
6168
6169 channel_hint = cds_freq_to_chan(nla_get_u32(tb
6170 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
6171
6172 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006173 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174 channel_hint, HW_MODE_20_MHZ)) {
6175 hdd_err("Set channel hint failed due to concurrency check");
6176 return -EINVAL;
6177 }
6178
Krunal Soni09e55032016-06-07 10:06:55 -07006179 if (0 != wlan_hdd_check_remain_on_channel(adapter))
6180 hdd_warn("Remain On Channel Pending");
6181
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006182 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006183 if (!QDF_IS_STATUS_SUCCESS(ret))
6184 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006185
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006186 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
6187 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07006188 SIR_UPDATE_REASON_SET_OPER_CHAN);
6189 if (QDF_STATUS_E_FAILURE == ret) {
6190 /* return in the failure case */
6191 hdd_err("ERROR: connections update failed!!");
6192 return -EINVAL;
6193 }
6194
6195 if (QDF_STATUS_SUCCESS == ret) {
6196 /*
6197 * Success is the only case for which we expect hw mode
6198 * change to take place, hence we need to wait.
6199 * For any other return value it should be a pass
6200 * through
6201 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006202 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006203 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6204 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006205 return -EINVAL;
6206 }
6207
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006208 }
6209
6210 return 0;
6211}
6212
6213/**
6214 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6215 * @wiphy: Pointer to wireless phy
6216 * @wdev: Pointer to wireless device
6217 * @data: Pointer to data
6218 * @data_len: Data length
6219 *
6220 * Return: 0 on success, negative errno on failure
6221 */
6222static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6223 struct wireless_dev *wdev,
6224 const void *data,
6225 int data_len)
6226{
6227 int ret = 0;
6228
6229 cds_ssr_protect(__func__);
6230 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6231 data, data_len);
6232 cds_ssr_unprotect(__func__);
6233
6234 return ret;
6235}
6236
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306237static const struct
6238nla_policy
6239qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6240 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6241};
6242
6243/**
6244 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6245 * @wiphy: WIPHY structure pointer
6246 * @wdev: Wireless device structure pointer
6247 * @data: Pointer to the data received
6248 * @data_len: Length of the data received
6249 *
6250 * This function is used to get link properties like nss, rate flags and
6251 * operating frequency for the active connection with the given peer.
6252 *
6253 * Return: 0 on success and errno on failure
6254 */
6255static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6256 struct wireless_dev *wdev,
6257 const void *data,
6258 int data_len)
6259{
6260 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6261 struct net_device *dev = wdev->netdev;
6262 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6263 hdd_station_ctx_t *hdd_sta_ctx;
6264 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306265 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306266 uint32_t sta_id;
6267 struct sk_buff *reply_skb;
6268 uint32_t rate_flags = 0;
6269 uint8_t nss;
6270 uint8_t final_rate_flags = 0;
6271 uint32_t freq;
6272
Jeff Johnson1f61b612016-02-12 16:28:33 -08006273 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306274
Anurag Chouhan6d760662016-02-20 16:05:43 +05306275 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306276 hdd_err("Command not allowed in FTM mode");
6277 return -EPERM;
6278 }
6279
6280 if (0 != wlan_hdd_validate_context(hdd_ctx))
6281 return -EINVAL;
6282
6283 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6284 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006285 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306286 return -EINVAL;
6287 }
6288
6289 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006290 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306291 adapter->device_mode);
6292 return -EINVAL;
6293 }
6294
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306295 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306296 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006297 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306298 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6299
Krunal Sonib4326f22016-03-10 13:05:51 -08006300 if (adapter->device_mode == QDF_STA_MODE ||
6301 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306302 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6303 if ((hdd_sta_ctx->conn_info.connState !=
6304 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306305 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306306 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006307 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306308 MAC_ADDR_ARRAY(peer_mac));
6309 return -EINVAL;
6310 }
6311
6312 nss = hdd_sta_ctx->conn_info.nss;
6313 freq = cds_chan_to_freq(
6314 hdd_sta_ctx->conn_info.operationChannel);
6315 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006316 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6317 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306318
6319 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6320 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306321 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306322 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306323 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306324 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306325 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306326 break;
6327 }
6328
6329 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006330 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306331 MAC_ADDR_ARRAY(peer_mac));
6332 return -EINVAL;
6333 }
6334
6335 nss = adapter->aStaInfo[sta_id].nss;
6336 freq = cds_chan_to_freq(
6337 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6338 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6339 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006340 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306341 MAC_ADDR_ARRAY(peer_mac));
6342 return -EINVAL;
6343 }
6344
6345 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6346 if (rate_flags & eHAL_TX_RATE_VHT80) {
6347 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006348#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306349 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006350#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306351 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6352 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006353#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306354 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006355#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306356 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6357 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6358 } else if (rate_flags &
6359 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6360 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006361#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306362 if (rate_flags & eHAL_TX_RATE_HT40)
6363 final_rate_flags |=
6364 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006365#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306366 }
6367
6368 if (rate_flags & eHAL_TX_RATE_SGI) {
6369 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6370 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6371 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6372 }
6373 }
6374
6375 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6376 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6377
6378 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006379 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306380 return -EINVAL;
6381 }
6382
6383 if (nla_put_u8(reply_skb,
6384 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6385 nss) ||
6386 nla_put_u8(reply_skb,
6387 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6388 final_rate_flags) ||
6389 nla_put_u32(reply_skb,
6390 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6391 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006392 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306393 kfree_skb(reply_skb);
6394 return -EINVAL;
6395 }
6396
6397 return cfg80211_vendor_cmd_reply(reply_skb);
6398}
6399
6400/**
6401 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6402 * properties.
6403 * @wiphy: WIPHY structure pointer
6404 * @wdev: Wireless device structure pointer
6405 * @data: Pointer to the data received
6406 * @data_len: Length of the data received
6407 *
6408 * This function is used to get link properties like nss, rate flags and
6409 * operating frequency for the active connection with the given peer.
6410 *
6411 * Return: 0 on success and errno on failure
6412 */
6413static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6414 struct wireless_dev *wdev,
6415 const void *data,
6416 int data_len)
6417{
6418 int ret = 0;
6419
6420 cds_ssr_protect(__func__);
6421 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6422 wdev, data, data_len);
6423 cds_ssr_unprotect(__func__);
6424
6425 return ret;
6426}
6427
Peng Xu278d0122015-09-24 16:34:17 -07006428static const struct
6429nla_policy
6430qca_wlan_vendor_ota_test_policy
6431[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6432 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6433};
6434
6435/**
6436 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6437 * @wiphy: Pointer to wireless phy
6438 * @wdev: Pointer to wireless device
6439 * @data: Pointer to data
6440 * @data_len: Data length
6441 *
6442 * Return: 0 on success, negative errno on failure
6443 */
6444static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6445 struct wireless_dev *wdev,
6446 const void *data,
6447 int data_len)
6448{
6449 struct net_device *dev = wdev->netdev;
6450 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6451 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6452 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6453 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6454 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306455 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006456 uint32_t current_roam_state;
6457
Jeff Johnson1f61b612016-02-12 16:28:33 -08006458 ENTER_DEV(dev);
6459
Anurag Chouhan6d760662016-02-20 16:05:43 +05306460 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006461 hdd_err("Command not allowed in FTM mode");
6462 return -EPERM;
6463 }
6464
6465 if (0 != wlan_hdd_validate_context(hdd_ctx))
6466 return -EINVAL;
6467
6468 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6469 data, data_len,
6470 qca_wlan_vendor_ota_test_policy)) {
6471 hdd_err("invalid attr");
6472 return -EINVAL;
6473 }
6474
6475 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6476 hdd_err("attr ota test failed");
6477 return -EINVAL;
6478 }
6479
6480 ota_enable = nla_get_u8(
6481 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6482
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006483 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006484 if (ota_enable != 1) {
6485 hdd_err("Invalid value, only enable test mode is supported!");
6486 return -EINVAL;
6487 }
6488
6489 current_roam_state =
6490 sme_get_current_roam_state(hal, adapter->sessionId);
6491 status = sme_stop_roaming(hal, adapter->sessionId,
6492 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306493 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006494 hdd_err("Enable/Disable roaming failed");
6495 return -EINVAL;
6496 }
6497
6498 status = sme_ps_enable_disable(hal, adapter->sessionId,
6499 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306500 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006501 hdd_err("Enable/Disable power save failed");
6502 /* restore previous roaming setting */
6503 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6504 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6505 status = sme_start_roaming(hal, adapter->sessionId,
6506 eCsrHddIssued);
6507 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6508 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6509 status = sme_stop_roaming(hal, adapter->sessionId,
6510 eCsrHddIssued);
6511
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306512 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006513 hdd_err("Restoring roaming state failed");
6514
6515 return -EINVAL;
6516 }
6517
6518
6519 return 0;
6520}
6521
6522/**
6523 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6524 * @wiphy: Pointer to wireless phy
6525 * @wdev: Pointer to wireless device
6526 * @data: Pointer to data
6527 * @data_len: Data length
6528 *
6529 * Return: 0 on success, negative errno on failure
6530 */
6531static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6532 struct wireless_dev *wdev,
6533 const void *data,
6534 int data_len)
6535{
6536 int ret = 0;
6537
6538 cds_ssr_protect(__func__);
6539 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6540 cds_ssr_unprotect(__func__);
6541
6542 return ret;
6543}
6544
Peng Xu4d67c8f2015-10-16 16:02:26 -07006545/**
6546 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6547 * @wiphy: Pointer to wireless phy
6548 * @wdev: Pointer to wireless device
6549 * @data: Pointer to data
6550 * @data_len: Data length
6551 *
6552 * Return: 0 on success, negative errno on failure
6553 */
6554static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6555 struct wireless_dev *wdev,
6556 const void *data,
6557 int data_len)
6558{
6559 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6560 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006561 hdd_adapter_t *adapter;
6562 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006563 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6564 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006565 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006566
Jeff Johnson1f61b612016-02-12 16:28:33 -08006567 ENTER_DEV(dev);
6568
Peng Xu4d67c8f2015-10-16 16:02:26 -07006569 ret = wlan_hdd_validate_context(hdd_ctx);
6570 if (ret)
6571 return ret;
6572
6573 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6574
6575 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6576 data, data_len, NULL)) {
6577 hdd_err("Invalid ATTR");
6578 return -EINVAL;
6579 }
6580
6581 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6582 hdd_err("attr tx power scale failed");
6583 return -EINVAL;
6584 }
6585
6586 scale_value = nla_get_u8(tb
6587 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6588
6589 if (scale_value > MAX_TXPOWER_SCALE) {
6590 hdd_err("Invalid tx power scale level");
6591 return -EINVAL;
6592 }
6593
Peng Xu62c8c432016-05-09 15:23:02 -07006594 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006595
Peng Xu62c8c432016-05-09 15:23:02 -07006596 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006597 hdd_err("Set tx power scale failed");
6598 return -EINVAL;
6599 }
6600
6601 return 0;
6602}
6603
6604/**
6605 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6606 * @wiphy: Pointer to wireless phy
6607 * @wdev: Pointer to wireless device
6608 * @data: Pointer to data
6609 * @data_len: Data length
6610 *
6611 * Return: 0 on success, negative errno on failure
6612 */
6613static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6614 struct wireless_dev *wdev,
6615 const void *data,
6616 int data_len)
6617{
Peng Xu62c8c432016-05-09 15:23:02 -07006618 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006619
6620 cds_ssr_protect(__func__);
6621 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6622 data, data_len);
6623 cds_ssr_unprotect(__func__);
6624
6625 return ret;
6626}
6627
6628/**
6629 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6630 * @wiphy: Pointer to wireless phy
6631 * @wdev: Pointer to wireless device
6632 * @data: Pointer to data
6633 * @data_len: Data length
6634 *
6635 * Return: 0 on success, negative errno on failure
6636 */
6637static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6638 struct wireless_dev *wdev,
6639 const void *data,
6640 int data_len)
6641{
6642 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6643 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006644 hdd_adapter_t *adapter;
6645 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006646 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6647 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006648 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006649
Jeff Johnson1f61b612016-02-12 16:28:33 -08006650 ENTER_DEV(dev);
6651
Peng Xu4d67c8f2015-10-16 16:02:26 -07006652 ret = wlan_hdd_validate_context(hdd_ctx);
6653 if (ret)
6654 return ret;
6655
6656 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6657
6658 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6659 data, data_len, NULL)) {
6660 hdd_err("Invalid ATTR");
6661 return -EINVAL;
6662 }
6663
6664 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6665 hdd_err("attr tx power decrease db value failed");
6666 return -EINVAL;
6667 }
6668
6669 scale_value = nla_get_u8(tb
6670 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6671
Peng Xu62c8c432016-05-09 15:23:02 -07006672 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6673 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006674
Peng Xu62c8c432016-05-09 15:23:02 -07006675 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006676 hdd_err("Set tx power decrease db failed");
6677 return -EINVAL;
6678 }
6679
6680 return 0;
6681}
6682
6683/**
6684 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6685 * @wiphy: Pointer to wireless phy
6686 * @wdev: Pointer to wireless device
6687 * @data: Pointer to data
6688 * @data_len: Data length
6689 *
6690 * Return: 0 on success, negative errno on failure
6691 */
6692static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6693 struct wireless_dev *wdev,
6694 const void *data,
6695 int data_len)
6696{
Peng Xu62c8c432016-05-09 15:23:02 -07006697 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006698
6699 cds_ssr_protect(__func__);
6700 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6701 data, data_len);
6702 cds_ssr_unprotect(__func__);
6703
6704 return ret;
6705}
Peng Xu8fdaa492016-06-22 10:20:47 -07006706
6707/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306708 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6709 * @wiphy: Pointer to wireless phy
6710 * @wdev: Pointer to wireless device
6711 * @data: Pointer to data
6712 * @data_len: Data length
6713 *
6714 * Processes the conditional channel switch request and invokes the helper
6715 * APIs to process the channel switch request.
6716 *
6717 * Return: 0 on success, negative errno on failure
6718 */
6719static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6720 struct wireless_dev *wdev,
6721 const void *data,
6722 int data_len)
6723{
6724 int ret;
6725 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6726 struct net_device *dev = wdev->netdev;
6727 hdd_adapter_t *adapter;
6728 struct nlattr
6729 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6730 uint32_t freq_len, i;
6731 uint32_t *freq;
6732 uint8_t chans[QDF_MAX_NUM_CHAN];
6733
6734 ENTER_DEV(dev);
6735
6736 ret = wlan_hdd_validate_context(hdd_ctx);
6737 if (ret)
6738 return ret;
6739
6740 if (!hdd_ctx->config->enableDFSMasterCap) {
6741 hdd_err("DFS master capability is not present in the driver");
6742 return -EINVAL;
6743 }
6744
6745 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6746 hdd_err("Command not allowed in FTM mode");
6747 return -EPERM;
6748 }
6749
6750 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6751 if (adapter->device_mode != QDF_SAP_MODE) {
6752 hdd_err("Invalid device mode %d", adapter->device_mode);
6753 return -EINVAL;
6754 }
6755
6756 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6757 data, data_len, NULL)) {
6758 hdd_err("Invalid ATTR");
6759 return -EINVAL;
6760 }
6761
6762 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6763 hdd_err("Frequency list is missing");
6764 return -EINVAL;
6765 }
6766
6767 freq_len = nla_len(
6768 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6769 sizeof(uint32_t);
6770
6771 if (freq_len > QDF_MAX_NUM_CHAN) {
6772 hdd_err("insufficient space to hold channels");
6773 return -ENOMEM;
6774 }
6775
6776 hdd_debug("freq_len=%d", freq_len);
6777
6778 freq = nla_data(
6779 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6780
6781
6782 for (i = 0; i < freq_len; i++) {
6783 if (freq[i] == 0)
6784 chans[i] = 0;
6785 else
6786 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6787
6788 hdd_debug("freq[%d]=%d", i, freq[i]);
6789 }
6790
6791 /*
6792 * The input frequency list from user space is designed to be a
6793 * priority based frequency list. This is only to accommodate any
6794 * future request. But, current requirement is only to perform CAC
6795 * on a single channel. So, the first entry from the list is picked.
6796 *
6797 * If channel is zero, any channel in the available outdoor regulatory
6798 * domain will be selected.
6799 */
6800 ret = wlan_hdd_request_pre_cac(chans[0]);
6801 if (ret) {
6802 hdd_err("pre cac request failed with reason:%d", ret);
6803 return ret;
6804 }
6805
6806 return 0;
6807}
6808
6809/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006810 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6811 * @wiphy: Pointer to wireless phy
6812 * @wdev: Pointer to wireless device
6813 * @data: Pointer to data
6814 * @data_len: Data length
6815 *
6816 * This function is to process the p2p listen offload start vendor
6817 * command. It parses the input parameters and invoke WMA API to
6818 * send the command to firmware.
6819 *
6820 * Return: 0 on success, negative errno on failure
6821 */
6822static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6823 struct wireless_dev *wdev,
6824 const void *data,
6825 int data_len)
6826{
6827 int ret;
6828 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6829 struct net_device *dev = wdev->netdev;
6830 hdd_adapter_t *adapter;
6831 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6832 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006833
6834 ENTER_DEV(dev);
6835
6836 ret = wlan_hdd_validate_context(hdd_ctx);
6837 if (ret)
6838 return ret;
6839
6840 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6841 hdd_err("Command not allowed in FTM mode");
6842 return -EPERM;
6843 }
6844
6845 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6846 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6847 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6848 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6849 hdd_err("Invalid device mode %d", adapter->device_mode);
6850 return -EINVAL;
6851 }
6852
6853 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6854 data, data_len, NULL)) {
6855 hdd_err("Invalid ATTR");
6856 return -EINVAL;
6857 }
6858
6859 memset(&params, 0, sizeof(params));
6860
6861 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6862 params.ctl_flags = 1; /* set to default value */
6863 else
6864 params.ctl_flags = nla_get_u32(tb
6865 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6866
6867 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6868 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6869 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6870 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6871 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6872 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6873 hdd_err("Attribute parsing failed");
6874 return -EINVAL;
6875 }
6876
6877 params.vdev_id = adapter->sessionId;
6878 params.freq = nla_get_u32(tb
6879 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6880 if ((params.freq != 2412) && (params.freq != 2437) &&
6881 (params.freq != 2462)) {
6882 hdd_err("Invalid listening channel: %d", params.freq);
6883 return -EINVAL;
6884 }
6885
6886 params.period = nla_get_u32(tb
6887 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6888 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6889 hdd_err("Invalid period: %d", params.period);
6890 return -EINVAL;
6891 }
6892
6893 params.interval = nla_get_u32(tb
6894 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6895 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6896 hdd_err("Invalid interval: %d", params.interval);
6897 return -EINVAL;
6898 }
6899
6900 params.count = nla_get_u32(tb
6901 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006902 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006903 hdd_err("Invalid count: %d", params.count);
6904 return -EINVAL;
6905 }
6906
6907 params.device_types = nla_data(tb
6908 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6909 if (params.device_types == NULL) {
6910 hdd_err("Invalid device types");
6911 return -EINVAL;
6912 }
6913
6914 params.dev_types_len = nla_len(tb
6915 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6916 if (params.dev_types_len < 8) {
6917 hdd_err("Invalid device type length: %d", params.dev_types_len);
6918 return -EINVAL;
6919 }
6920
6921 params.probe_resp_tmplt = nla_data(tb
6922 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6923 if (params.probe_resp_tmplt == NULL) {
6924 hdd_err("Invalid probe response template");
6925 return -EINVAL;
6926 }
6927
6928 params.probe_resp_len = nla_len(tb
6929 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6930 if (params.probe_resp_len == 0) {
6931 hdd_err("Invalid probe resp template length: %d",
6932 params.probe_resp_len);
6933 return -EINVAL;
6934 }
6935
6936 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6937 params.freq, params.period, params.interval, params.count);
6938
Wu Gao9a704f42017-03-10 18:42:11 +08006939 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006940}
6941
6942
6943/**
6944 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6945 * @wiphy: Pointer to wireless phy
6946 * @wdev: Pointer to wireless device
6947 * @data: Pointer to data
6948 * @data_len: Data length
6949 *
6950 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6951 * to process p2p listen offload start vendor command.
6952 *
6953 * Return: 0 on success, negative errno on failure
6954 */
6955static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6956 struct wireless_dev *wdev,
6957 const void *data,
6958 int data_len)
6959{
6960 int ret = 0;
6961
6962 cds_ssr_protect(__func__);
6963 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6964 data, data_len);
6965 cds_ssr_unprotect(__func__);
6966
6967 return ret;
6968}
6969
6970/**
6971 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6972 * @wiphy: Pointer to wireless phy
6973 * @wdev: Pointer to wireless device
6974 * @data: Pointer to data
6975 * @data_len: Data length
6976 *
6977 * This function is to process the p2p listen offload stop vendor
6978 * command. It invokes WMA API to send command to firmware.
6979 *
6980 * Return: 0 on success, negative errno on failure
6981 */
6982static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6983 struct wireless_dev *wdev,
6984 const void *data,
6985 int data_len)
6986{
Peng Xu8fdaa492016-06-22 10:20:47 -07006987 hdd_adapter_t *adapter;
6988 struct net_device *dev = wdev->netdev;
6989
6990 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6991 hdd_err("Command not allowed in FTM mode");
6992 return -EPERM;
6993 }
6994
6995 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6996 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6997 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6998 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6999 hdd_err("Invalid device mode");
7000 return -EINVAL;
7001 }
7002
Wu Gao9a704f42017-03-10 18:42:11 +08007003 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07007004}
7005
7006/**
7007 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7008 * @wiphy: Pointer to wireless phy
7009 * @wdev: Pointer to wireless device
7010 * @data: Pointer to data
7011 * @data_len: Data length
7012 *
7013 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
7014 * to process p2p listen offload stop vendor command.
7015 *
7016 * Return: 0 on success, negative errno on failure
7017 */
7018static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7019 struct wireless_dev *wdev,
7020 const void *data,
7021 int data_len)
7022{
7023 int ret = 0;
7024
7025 cds_ssr_protect(__func__);
7026 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
7027 data, data_len);
7028 cds_ssr_unprotect(__func__);
7029
7030 return ret;
7031}
7032
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307033/**
7034 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
7035 * @wiphy: Pointer to wireless phy
7036 * @wdev: Pointer to wireless device
7037 * @data: Pointer to data
7038 * @data_len: Data length
7039 *
7040 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
7041 * to process the conditional channel switch request.
7042 *
7043 * Return: 0 on success, negative errno on failure
7044 */
7045static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
7046 struct wireless_dev *wdev,
7047 const void *data,
7048 int data_len)
7049{
7050 int ret;
7051
7052 cds_ssr_protect(__func__);
7053 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
7054 data, data_len);
7055 cds_ssr_unprotect(__func__);
7056
7057 return ret;
7058}
7059
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307060/*
7061 * define short names for the global vendor params
7062 * used by __wlan_hdd_cfg80211_bpf_offload()
7063 */
7064#define BPF_INVALID \
7065 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
7066#define BPF_SET_RESET \
7067 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
7068#define BPF_VERSION \
7069 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
7070#define BPF_FILTER_ID \
7071 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
7072#define BPF_PACKET_SIZE \
7073 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
7074#define BPF_CURRENT_OFFSET \
7075 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
7076#define BPF_PROGRAM \
7077 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
7078#define BPF_MAX \
7079 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07007080
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307081static const struct nla_policy
7082wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
7083 [BPF_SET_RESET] = {.type = NLA_U32},
7084 [BPF_VERSION] = {.type = NLA_U32},
7085 [BPF_FILTER_ID] = {.type = NLA_U32},
7086 [BPF_PACKET_SIZE] = {.type = NLA_U32},
7087 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
7088 [BPF_PROGRAM] = {.type = NLA_U8},
7089};
7090
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007091struct bpf_offload_priv {
7092 struct sir_bpf_get_offload bpf_get_offload;
7093};
7094
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307095/**
7096 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007097 * @context: opaque context originally passed to SME. HDD always passes
7098 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307099 * @bpf_get_offload: struct for get offload
7100 *
7101 * This function receives the response/data from the lower layer and
7102 * checks to see if the thread is still waiting then post the results to
7103 * upper layer, if the request has timed out then ignore.
7104 *
7105 * Return: None
7106 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007107static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007108 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307109{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007110 struct hdd_request *request;
7111 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307112
7113 ENTER();
7114
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007115 request = hdd_request_get(context);
7116 if (!request) {
7117 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307118 return;
7119 }
7120
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007121 priv = hdd_request_priv(request);
7122 priv->bpf_get_offload = *data;
7123 hdd_request_complete(request);
7124 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307125}
7126
7127/**
7128 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
7129 * @hdd_context: hdd_context
7130 * @bpf_get_offload: struct for get offload
7131 *
7132 * Return: 0 on success, error number otherwise.
7133 */
7134static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
7135 struct sir_bpf_get_offload *bpf_get_offload)
7136{
7137 struct sk_buff *skb;
7138 uint32_t nl_buf_len;
7139
7140 ENTER();
7141
7142 nl_buf_len = NLMSG_HDRLEN;
7143 nl_buf_len +=
7144 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
7145 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
7146
7147 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7148 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007149 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307150 return -ENOMEM;
7151 }
7152
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007153 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307154 bpf_get_offload->bpf_version,
7155 bpf_get_offload->max_bytes_for_bpf_inst);
7156
7157 if (nla_put_u32(skb, BPF_PACKET_SIZE,
7158 bpf_get_offload->max_bytes_for_bpf_inst) ||
7159 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007160 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307161 goto nla_put_failure;
7162 }
7163
7164 cfg80211_vendor_cmd_reply(skb);
7165 EXIT();
7166 return 0;
7167
7168nla_put_failure:
7169 kfree_skb(skb);
7170 return -EINVAL;
7171}
7172
7173/**
7174 * hdd_get_bpf_offload - Get BPF offload Capabilities
7175 * @hdd_ctx: Hdd context
7176 *
7177 * Return: 0 on success, errno on failure
7178 */
7179static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
7180{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307181 QDF_STATUS status;
7182 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007183 void *cookie;
7184 struct hdd_request *request;
7185 struct bpf_offload_priv *priv;
7186 static const struct hdd_request_params params = {
7187 .priv_size = sizeof(*priv),
7188 .timeout_ms = WLAN_WAIT_TIME_BPF,
7189 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307190
7191 ENTER();
7192
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007193 request = hdd_request_alloc(&params);
7194 if (!request) {
7195 hdd_err("Unable to allocate request");
7196 return -EINVAL;
7197 }
7198 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307199
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007200 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7201 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007202 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307203 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007204 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007205 ret = qdf_status_to_os_return(status);
7206 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307207 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007208 ret = hdd_request_wait_for_response(request);
7209 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007210 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007211 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307212 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007213 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307214 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007215 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307216 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007217 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307218
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007219cleanup:
7220 /*
7221 * either we never sent a request to SME, we sent a request to
7222 * SME and timed out, or we sent a request to SME, received a
7223 * response from SME, and posted the response to userspace.
7224 * regardless we are done with the request.
7225 */
7226 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307227 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007228
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307229 return ret;
7230}
7231
7232/**
7233 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7234 * @hdd_ctx: Hdd context
7235 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307236 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307237 *
7238 * Return: 0 on success; errno on failure
7239 */
7240static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7241 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307242 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307243{
7244 struct sir_bpf_set_offload *bpf_set_offload;
7245 QDF_STATUS status;
7246 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307247 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307248
7249 ENTER();
7250
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307251 if (adapter->device_mode == QDF_STA_MODE ||
7252 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7253 if (!hdd_conn_is_connected(
7254 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7255 hdd_err("Not in Connected state!");
7256 return -ENOTSUPP;
7257 }
7258 }
7259
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307260 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7261 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007262 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307263 return -ENOMEM;
7264 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307265
7266 /* Parse and fetch bpf packet size */
7267 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007268 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307269 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307270 goto fail;
7271 }
7272 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7273
7274 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007275 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307276 goto post_sme;
7277 }
7278
7279 /* Parse and fetch bpf program */
7280 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007281 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307282 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307283 goto fail;
7284 }
7285
7286 prog_len = nla_len(tb[BPF_PROGRAM]);
7287 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307288
7289 if (bpf_set_offload->program == NULL) {
7290 hdd_err("qdf_mem_malloc failed for bpf offload program");
7291 ret = -ENOMEM;
7292 goto fail;
7293 }
7294
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307295 bpf_set_offload->current_length = prog_len;
7296 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307297 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307298
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007299 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007300 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307301 bpf_set_offload->program, prog_len);
7302
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307303 /* Parse and fetch filter Id */
7304 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007305 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307306 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307307 goto fail;
7308 }
7309 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7310
7311 /* Parse and fetch current offset */
7312 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007313 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307314 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307315 goto fail;
7316 }
7317 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7318
7319post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007320 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 +05307321 bpf_set_offload->session_id,
7322 bpf_set_offload->version,
7323 bpf_set_offload->filter_id,
7324 bpf_set_offload->total_length,
7325 bpf_set_offload->current_length,
7326 bpf_set_offload->current_offset);
7327
7328 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7329 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007330 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307331 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307332 goto fail;
7333 }
7334 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307335
7336fail:
7337 if (bpf_set_offload->current_length)
7338 qdf_mem_free(bpf_set_offload->program);
7339 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307340 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307341}
7342
7343/**
7344 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7345 * @wiphy: wiphy structure pointer
7346 * @wdev: Wireless device structure pointer
7347 * @data: Pointer to the data received
7348 * @data_len: Length of @data
7349 *
7350 * Return: 0 on success; errno on failure
7351 */
7352static int
7353__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7354 struct wireless_dev *wdev,
7355 const void *data, int data_len)
7356{
7357 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7358 struct net_device *dev = wdev->netdev;
7359 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7360 struct nlattr *tb[BPF_MAX + 1];
7361 int ret_val, packet_filter_subcmd;
7362
7363 ENTER();
7364
7365 ret_val = wlan_hdd_validate_context(hdd_ctx);
7366 if (ret_val)
7367 return ret_val;
7368
7369 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007370 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307371 return -EINVAL;
7372 }
7373
7374 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007375 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307376 return -ENOTSUPP;
7377 }
7378
7379 if (nla_parse(tb, BPF_MAX, data, data_len,
7380 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007381 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307382 return -EINVAL;
7383 }
7384
7385 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007386 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307387 return -EINVAL;
7388 }
7389
7390 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7391
7392 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7393 return hdd_get_bpf_offload(hdd_ctx);
7394 else
7395 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307396 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307397}
7398
7399/**
7400 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7401 * @wiphy: wiphy structure pointer
7402 * @wdev: Wireless device structure pointer
7403 * @data: Pointer to the data received
7404 * @data_len: Length of @data
7405 *
7406 * Return: 0 on success; errno on failure
7407 */
7408
7409static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7410 struct wireless_dev *wdev,
7411 const void *data, int data_len)
7412{
7413 int ret;
7414
7415 cds_ssr_protect(__func__);
7416 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7417 cds_ssr_unprotect(__func__);
7418
7419 return ret;
7420}
7421
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307422/**
7423 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7424 * @pre_cac_adapter: AP adapter used for pre cac
7425 * @status: Status (true or false)
7426 * @handle: Global handle
7427 *
7428 * Sets the status of pre cac i.e., whether the pre cac is active or not
7429 *
7430 * Return: Zero on success, non-zero on failure
7431 */
7432static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7433 bool status, tHalHandle handle)
7434{
7435 QDF_STATUS ret;
7436
7437 ret = wlan_sap_set_pre_cac_status(
7438 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7439 if (QDF_IS_STATUS_ERROR(ret))
7440 return -EINVAL;
7441
7442 return 0;
7443}
7444
7445/**
7446 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7447 * @ap_adapter: AP adapter
7448 * @chan_before_pre_cac: Channel
7449 *
7450 * Saves the channel which the AP was beaconing on before moving to the pre
7451 * cac channel. If radar is detected on the pre cac channel, this saved
7452 * channel will be used for AP operations.
7453 *
7454 * Return: Zero on success, non-zero on failure
7455 */
7456static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7457 uint8_t chan_before_pre_cac)
7458{
7459 QDF_STATUS ret;
7460
7461 ret = wlan_sap_set_chan_before_pre_cac(
7462 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7463 if (QDF_IS_STATUS_ERROR(ret))
7464 return -EINVAL;
7465
7466 return 0;
7467}
7468
7469/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307470 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7471 * are in nol list from provided channel list
7472 * @adapter: AP adapter
7473 * @channel_count: channel count
7474 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307475 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307476 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307477 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307478static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7479 uint32_t *channel_count,
7480 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307481{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307482 uint8_t i, j;
7483 uint32_t nol_len = 0;
7484 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7485 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7486 uint32_t chan_count;
7487 bool found;
7488 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307489
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307490 if (!hdd_ctx) {
7491 hdd_err("hdd ctx not found");
7492 *channel_count = 0;
7493 return;
7494 }
7495
7496 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7497 hdd_err("invalid channel count %d", *channel_count);
7498 return;
7499 }
7500
7501 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7502 if (nol_len == 0)
7503 return;
7504
7505 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7506 chan_count = *channel_count;
7507 qdf_mem_zero(channel_list, chan_count);
7508 *channel_count = 0;
7509
7510 for (i = 0 ; i < chan_count; i++) {
7511 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7512 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7513 continue;
7514 found = false;
7515 for (j = 0; j < nol_len; j++) {
7516 if (tmp_chan_list[i] == nol[j]) {
7517 found = true;
7518 hdd_notice("skipped channel %d due to nol",
7519 nol[j]);
7520 break;
7521 }
7522 }
7523 if (!found) {
7524 channel_list[*channel_count] = tmp_chan_list[i];
7525 *channel_count = *channel_count + 1;
7526 }
7527 }
7528}
7529
7530int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7531 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307532 uint8_t *channel_list,
7533 eCsrBand band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307534{
7535 tsap_Config_t *sap_config;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307536 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7537 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7538 uint32_t chan_count;
7539 uint8_t i;
7540 QDF_STATUS status;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307541
7542 sap_config = &adapter->sessionCtx.ap.sapConfig;
7543
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307544 status =
7545 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7546 tmp_chan_list,
7547 &chan_count);
7548 if (QDF_IS_STATUS_ERROR(status)) {
7549 hdd_err("Failed to get channel list");
7550 return -EINVAL;
7551 }
7552 for (i = 0; i < chan_count; i++) {
7553 if (*channel_count < QDF_MAX_NUM_CHAN) {
7554 if ((eCSR_BAND_24 == band) &&
7555 (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
7556 channel_list[*channel_count] = tmp_chan_list[i];
7557 *channel_count += 1;
7558 } else if ((eCSR_BAND_5G == band) &&
7559 (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
7560 channel_list[*channel_count] = tmp_chan_list[i];
7561 *channel_count += 1;
7562 }
7563 } else {
7564 break;
7565 }
7566 }
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307567 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307568 if (*channel_count == 0) {
7569 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307570 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307571 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307572
7573 return 0;
7574}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307575
7576/**
7577 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7578 * @hdd_ctx: HDD context
7579 * @ap_adapter: AP adapter
7580 * @channel: Channel requested by userspace
7581 * @pre_cac_chan: Pointer to the pre CAC channel
7582 *
7583 * Validates the channel provided by userspace. If user provided channel 0,
7584 * a valid outdoor channel must be selected from the regulatory channel.
7585 *
7586 * Return: Zero on success and non zero value on error
7587 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007588static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7589 hdd_adapter_t *ap_adapter,
7590 uint8_t channel,
7591 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307592{
7593 uint32_t i, j;
7594 QDF_STATUS status;
7595 int ret;
7596 uint8_t nol[QDF_MAX_NUM_CHAN];
7597 uint32_t nol_len = 0, weight_len = 0;
7598 bool found;
7599 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7600 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7601 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7602
7603 if (0 == channel) {
7604 /* Channel is not obtained from PCL because PCL may not have
7605 * the entire channel list. For example: if SAP is up on
7606 * channel 6 and PCL is queried for the next SAP interface,
7607 * if SCC is preferred, the PCL will contain only the channel
7608 * 6. But, we are in need of a DFS channel. So, going with the
7609 * first channel from the valid channel list.
7610 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007611 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7612 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307613 if (QDF_IS_STATUS_ERROR(status)) {
7614 hdd_err("Failed to get channel list");
7615 return -EINVAL;
7616 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007617 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307618 pcl_weights, weight_len);
7619 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7620 for (i = 0; i < len; i++) {
7621 found = false;
7622 for (j = 0; j < nol_len; j++) {
7623 if (channel_list[i] == nol[j]) {
7624 found = true;
7625 break;
7626 }
7627 }
7628 if (found)
7629 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007630 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7631 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307632 *pre_cac_chan = channel_list[i];
7633 break;
7634 }
7635 }
7636 if (*pre_cac_chan == 0) {
7637 hdd_err("unable to find outdoor channel");
7638 return -EINVAL;
7639 }
7640 } else {
7641 /* Only when driver selects a channel, check is done for
7642 * unnsafe and NOL channels. When user provides a fixed channel
7643 * the user is expected to take care of this.
7644 */
7645 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007646 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307647 hdd_err("Invalid channel for pre cac:%d", channel);
7648 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307649 }
Jeff Johnson68755312017-02-10 11:46:55 -08007650
7651 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307652 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007653 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307654 return 0;
7655}
7656
7657/**
7658 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7659 * @channel: Channel option provided by userspace
7660 *
7661 * Sets the driver to the required hardware mode and start an adapater for
7662 * pre CAC which will mimic an AP.
7663 *
7664 * Return: Zero on success, non-zero value on error
7665 */
7666int wlan_hdd_request_pre_cac(uint8_t channel)
7667{
Krunal Sonib37bb352016-12-20 14:12:21 -08007668 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307669 hdd_context_t *hdd_ctx;
7670 int ret;
7671 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7672 hdd_ap_ctx_t *hdd_ap_ctx;
7673 QDF_STATUS status;
7674 struct wiphy *wiphy;
7675 struct net_device *dev;
7676 struct cfg80211_chan_def chandef;
7677 enum nl80211_channel_type channel_type;
7678 uint32_t freq;
7679 struct ieee80211_channel *chan;
7680 tHalHandle handle;
7681 bool val;
7682
7683 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7684 if (0 != wlan_hdd_validate_context(hdd_ctx))
7685 return -EINVAL;
7686
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007687 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307688 hdd_err("pre cac not allowed in concurrency");
7689 return -EINVAL;
7690 }
7691
7692 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7693 if (!ap_adapter) {
7694 hdd_err("unable to get SAP adapter");
7695 return -EINVAL;
7696 }
7697
7698 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7699 if (!handle) {
7700 hdd_err("Invalid handle");
7701 return -EINVAL;
7702 }
7703
7704 val = wlan_sap_is_pre_cac_active(handle);
7705 if (val) {
7706 hdd_err("pre cac is already in progress");
7707 return -EINVAL;
7708 }
7709
7710 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7711 if (!hdd_ap_ctx) {
7712 hdd_err("SAP context is NULL");
7713 return -EINVAL;
7714 }
7715
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007716 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7717 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307718 hdd_err("SAP is already on DFS channel:%d",
7719 hdd_ap_ctx->operatingChannel);
7720 return -EINVAL;
7721 }
7722
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007723 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307724 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7725 hdd_ap_ctx->operatingChannel);
7726 return -EINVAL;
7727 }
7728
Krunal Sonib37bb352016-12-20 14:12:21 -08007729 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7730 if (!mac_addr) {
7731 hdd_err("can't add virtual intf: Not getting valid mac addr");
7732 return -EINVAL;
7733 }
7734
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007735 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307736
7737 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7738 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007739 if (ret != 0) {
7740 hdd_err("can't validate pre-cac channel");
7741 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307742 }
7743
7744 hdd_debug("starting pre cac SAP adapter");
7745
7746 /* Starting a SAP adapter:
7747 * Instead of opening an adapter, we could just do a SME open session
7748 * for AP type. But, start BSS would still need an adapter.
7749 * So, this option is not taken.
7750 *
7751 * hdd open adapter is going to register this precac interface with
7752 * user space. This interface though exposed to user space will be in
7753 * DOWN state. Consideration was done to avoid this registration to the
7754 * user space. But, as part of SAP operations multiple events are sent
7755 * to user space. Some of these events received from unregistered
7756 * interface was causing crashes. So, retaining the registration.
7757 *
7758 * So, this interface would remain registered and will remain in DOWN
7759 * state for the CAC duration. We will add notes in the feature
7760 * announcement to not use this temporary interface for any activity
7761 * from user space.
7762 */
7763 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007764 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307765 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307766 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007767 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307768 }
7769
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307770 /*
7771 * This interface is internally created by the driver. So, no interface
7772 * up comes for this interface from user space and hence starting
7773 * the adapter internally.
7774 */
7775 if (hdd_start_adapter(pre_cac_adapter)) {
7776 hdd_err("error starting the pre cac adapter");
7777 goto close_pre_cac_adapter;
7778 }
7779
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307780 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7781
7782 wiphy = hdd_ctx->wiphy;
7783 dev = pre_cac_adapter->dev;
7784
7785 /* Since this is only a dummy interface lets us use the IEs from the
7786 * other active SAP interface. In regular scenarios, these IEs would
7787 * come from the user space entity
7788 */
7789 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7790 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7791 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7792 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307793 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307794 }
7795 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7796 ap_adapter->sessionCtx.ap.beacon,
7797 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7798 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7799 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7800 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7801 ap_adapter->sessionCtx.ap.sapConfig.authType;
7802
7803 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7804 * to operate on the same bandwidth as that of the 2.4GHz operations.
7805 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7806 */
7807 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7808 case CH_WIDTH_20MHZ:
7809 channel_type = NL80211_CHAN_HT20;
7810 break;
7811 case CH_WIDTH_40MHZ:
7812 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7813 ap_adapter->sessionCtx.ap.sapConfig.channel)
7814 channel_type = NL80211_CHAN_HT40PLUS;
7815 else
7816 channel_type = NL80211_CHAN_HT40MINUS;
7817 break;
7818 default:
7819 channel_type = NL80211_CHAN_NO_HT;
7820 break;
7821 }
7822
7823 freq = cds_chan_to_freq(pre_cac_chan);
7824 chan = __ieee80211_get_channel(wiphy, freq);
7825 if (!chan) {
7826 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307827 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307828 }
7829
7830 cfg80211_chandef_create(&chandef, chan, channel_type);
7831
7832 hdd_debug("orig width:%d channel_type:%d freq:%d",
7833 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7834 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007835 /*
7836 * Doing update after opening and starting pre-cac adapter will make
7837 * sure that driver won't do hardware mode change if there are any
7838 * initial hick-ups or issues in pre-cac adapter's configuration.
7839 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7840 * connection update should result in DBS mode
7841 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007842 status = policy_mgr_update_and_wait_for_connection_update(
7843 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007844 ap_adapter->sessionId,
7845 pre_cac_chan,
7846 SIR_UPDATE_REASON_PRE_CAC);
7847 if (QDF_IS_STATUS_ERROR(status)) {
7848 hdd_err("error in moving to DBS mode");
7849 goto stop_close_pre_cac_adapter;
7850 }
7851
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307852
7853 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7854 if (0 != ret) {
7855 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307856 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307857 }
7858
7859 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7860 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007861 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307862 if (QDF_IS_STATUS_ERROR(status)) {
7863 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307864 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307865 }
7866
7867 /*
7868 * The pre cac status is set here. But, it would not be reset explicitly
7869 * anywhere, since after the pre cac success/failure, the pre cac
7870 * adapter itself would be removed.
7871 */
7872 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7873 if (0 != ret) {
7874 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307875 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307876 }
7877
7878 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7879 hdd_ap_ctx->operatingChannel);
7880 if (0 != ret) {
7881 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307882 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307883 }
7884
7885 ap_adapter->pre_cac_chan = pre_cac_chan;
7886
7887 return 0;
7888
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307889stop_close_pre_cac_adapter:
7890 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307891 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7892 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307893close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307894 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007895release_intf_addr_and_return_failure:
7896 /*
7897 * Release the interface address as the adapter
7898 * failed to start, if you don't release then next
7899 * adapter which is trying to come wouldn't get valid
7900 * mac address. Remember we have limited pool of mac addresses
7901 */
7902 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307903 return -EINVAL;
7904}
7905
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307906static const struct nla_policy
7907wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7908 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7909};
7910
Agrawal Ashish65634612016-08-18 13:24:32 +05307911static const struct nla_policy
7912wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7913 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7914 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7915};
7916
7917/**
7918 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7919 * @wiphy: Pointer to wireless phy
7920 * @wdev: Pointer to wireless device
7921 * @data: Pointer to data
7922 * @data_len: Length of @data
7923 *
7924 * This function parses the incoming NL vendor command data attributes and
7925 * updates the SAP context about channel_hint and DFS mode.
7926 * If channel_hint is set, SAP will choose that channel
7927 * as operating channel.
7928 *
7929 * If DFS mode is enabled, driver will include DFS channels
7930 * in ACS else driver will skip DFS channels.
7931 *
7932 * Return: 0 on success, negative errno on failure
7933 */
7934static int
7935__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7936 struct wireless_dev *wdev,
7937 const void *data, int data_len)
7938{
7939 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7940 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7941 int ret;
7942 struct acs_dfs_policy *acs_policy;
7943 int mode = DFS_MODE_NONE;
7944 int channel_hint = 0;
7945
7946 ENTER_DEV(wdev->netdev);
7947
7948 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7949 hdd_err("Command not allowed in FTM mode");
7950 return -EINVAL;
7951 }
7952
7953 ret = wlan_hdd_validate_context(hdd_ctx);
7954 if (0 != ret)
7955 return ret;
7956
7957 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7958 data, data_len,
7959 wlan_hdd_set_acs_dfs_config_policy)) {
7960 hdd_err("invalid attr");
7961 return -EINVAL;
7962 }
7963
7964 acs_policy = &hdd_ctx->acs_policy;
7965 /*
7966 * SCM sends this attribute to restrict SAP from choosing
7967 * DFS channels from ACS.
7968 */
7969 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7970 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7971
7972 if (!IS_DFS_MODE_VALID(mode)) {
7973 hdd_err("attr acs dfs mode is not valid");
7974 return -EINVAL;
7975 }
7976 acs_policy->acs_dfs_mode = mode;
7977
7978 /*
7979 * SCM sends this attribute to provide an active channel,
7980 * to skip redundant ACS between drivers, and save driver start up time
7981 */
7982 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7983 channel_hint = nla_get_u8(
7984 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7985
7986 if (!IS_CHANNEL_VALID(channel_hint)) {
7987 hdd_err("acs channel is not valid");
7988 return -EINVAL;
7989 }
7990 acs_policy->acs_channel = channel_hint;
7991
7992 return 0;
7993}
7994
7995/**
7996 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7997 * @wiphy: wiphy structure pointer
7998 * @wdev: Wireless device structure pointer
7999 * @data: Pointer to the data received
8000 * @data_len: Length of @data
8001 *
8002 * This function parses the incoming NL vendor command data attributes and
8003 * updates the SAP context about channel_hint and DFS mode.
8004 *
8005 * Return: 0 on success; errno on failure
8006 */
8007static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8008 struct wireless_dev *wdev,
8009 const void *data, int data_len)
8010{
8011 int ret;
8012
8013 cds_ssr_protect(__func__);
8014 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
8015 cds_ssr_unprotect(__func__);
8016
8017 return ret;
8018}
8019
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308020/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308021 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
8022 * @mode : cfg80211 dfs mode
8023 *
8024 * Return: return csr sta roam dfs mode else return NONE
8025 */
8026static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
8027 enum dfs_mode mode)
8028{
8029 switch (mode) {
8030 case DFS_MODE_ENABLE:
8031 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
8032 break;
8033 case DFS_MODE_DISABLE:
8034 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
8035 break;
8036 case DFS_MODE_DEPRIORITIZE:
8037 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
8038 break;
8039 default:
8040 hdd_err("STA Roam policy dfs mode is NONE");
8041 return CSR_STA_ROAM_POLICY_NONE;
8042 }
8043}
8044
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308045/*
8046 * hdd_get_sap_operating_band: Get current operating channel
8047 * for sap.
8048 * @hdd_ctx: hdd context
8049 *
8050 * Return : Corresponding band for SAP operating channel
8051 */
8052uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
8053{
8054 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8055 QDF_STATUS status;
8056 hdd_adapter_t *adapter;
8057 uint8_t operating_channel = 0;
8058 uint8_t sap_operating_band = 0;
8059 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8060 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8061 adapter = adapter_node->pAdapter;
8062
8063 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
8064 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8065 &next);
8066 adapter_node = next;
8067 continue;
8068 }
8069 operating_channel = adapter->sessionCtx.ap.operatingChannel;
8070 if (IS_24G_CH(operating_channel))
8071 sap_operating_band = eCSR_BAND_24;
8072 else if (IS_5G_CH(operating_channel))
8073 sap_operating_band = eCSR_BAND_5G;
8074 else
8075 sap_operating_band = eCSR_BAND_ALL;
8076 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8077 &next);
bings373b99b2017-01-23 10:35:08 +08008078 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308079 }
8080 return sap_operating_band;
8081}
8082
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308083static const struct nla_policy
8084wlan_hdd_set_sta_roam_config_policy[
8085QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
8086 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
8087 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
8088};
8089
8090/**
8091 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
8092 * for station connection or roaming.
8093 * @wiphy: Pointer to wireless phy
8094 * @wdev: Pointer to wireless device
8095 * @data: Pointer to data
8096 * @data_len: Length of @data
8097 *
8098 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8099 * channels needs to be skipped in scanning or not.
8100 * If dfs_mode is disabled, driver will not scan DFS channels.
8101 * If skip_unsafe_channels is set, driver will skip unsafe channels
8102 * in Scanning.
8103 *
8104 * Return: 0 on success, negative errno on failure
8105 */
8106static int
8107__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8108 struct wireless_dev *wdev,
8109 const void *data, int data_len)
8110{
8111 struct net_device *dev = wdev->netdev;
8112 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8113 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8114 struct nlattr *tb[
8115 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8116 int ret;
8117 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8118 enum dfs_mode mode = DFS_MODE_NONE;
8119 bool skip_unsafe_channels = false;
8120 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308121 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308122
8123 ENTER_DEV(dev);
8124
8125 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8126 hdd_err("Command not allowed in FTM mode");
8127 return -EINVAL;
8128 }
8129
8130 ret = wlan_hdd_validate_context(hdd_ctx);
8131 if (0 != ret)
8132 return ret;
8133 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8134 data, data_len,
8135 wlan_hdd_set_sta_roam_config_policy)) {
8136 hdd_err("invalid attr");
8137 return -EINVAL;
8138 }
8139 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8140 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8141 if (!IS_DFS_MODE_VALID(mode)) {
8142 hdd_err("attr sta roam dfs mode policy is not valid");
8143 return -EINVAL;
8144 }
8145
8146 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8147
8148 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8149 skip_unsafe_channels = nla_get_u8(
8150 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308151 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308152 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308153 skip_unsafe_channels, adapter->sessionId,
8154 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308155
8156 if (!QDF_IS_STATUS_SUCCESS(status)) {
8157 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8158 return -EINVAL;
8159 }
8160 return 0;
8161}
8162
8163/**
8164 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8165 * connection and roaming for station.
8166 * @wiphy: wiphy structure pointer
8167 * @wdev: Wireless device structure pointer
8168 * @data: Pointer to the data received
8169 * @data_len: Length of @data
8170 *
8171 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8172 * channels needs to be skipped in scanning or not.
8173 * If dfs_mode is disabled, driver will not scan DFS channels.
8174 * If skip_unsafe_channels is set, driver will skip unsafe channels
8175 * in Scanning.
8176 * Return: 0 on success; errno on failure
8177 */
8178static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8179 struct wireless_dev *wdev,
8180 const void *data, int data_len)
8181{
8182 int ret;
8183
8184 cds_ssr_protect(__func__);
8185 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
8186 cds_ssr_unprotect(__func__);
8187
8188 return ret;
8189}
8190
Agrawal Ashish467dde42016-09-08 18:44:22 +05308191#ifdef FEATURE_WLAN_CH_AVOID
8192/**
8193 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8194 * is on unsafe channel.
8195 * @wiphy: wiphy structure pointer
8196 * @wdev: Wireless device structure pointer
8197 * @data: Pointer to the data received
8198 * @data_len: Length of @data
8199 *
8200 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8201 * on any of unsafe channels.
8202 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8203 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8204 *
8205 * Return: 0 on success; errno on failure
8206 */
8207static int
8208__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8209 struct wireless_dev *wdev,
8210 const void *data, int data_len)
8211{
8212 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8213 int ret;
8214 uint16_t unsafe_channel_count;
8215 int unsafe_channel_index;
8216 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8217
8218 ENTER_DEV(wdev->netdev);
8219
8220 if (!qdf_ctx) {
8221 cds_err("qdf_ctx is NULL");
8222 return -EINVAL;
8223 }
8224
8225 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8226 hdd_err("Command not allowed in FTM mode");
8227 return -EINVAL;
8228 }
8229
8230 ret = wlan_hdd_validate_context(hdd_ctx);
8231 if (0 != ret)
8232 return ret;
8233 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8234 &(hdd_ctx->unsafe_channel_count),
8235 sizeof(hdd_ctx->unsafe_channel_list));
8236
8237 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8238 (uint16_t)NUM_CHANNELS);
8239 for (unsafe_channel_index = 0;
8240 unsafe_channel_index < unsafe_channel_count;
8241 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008242 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308243 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8244 }
8245 hdd_unsafe_channel_restart_sap(hdd_ctx);
8246 return 0;
8247}
8248
8249/**
8250 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8251 * is on unsafe channel.
8252 * @wiphy: wiphy structure pointer
8253 * @wdev: Wireless device structure pointer
8254 * @data: Pointer to the data received
8255 * @data_len: Length of @data
8256 *
8257 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8258 * on any of unsafe channels.
8259 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8260 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8261 *
8262 * Return: 0 on success; errno on failure
8263 */
8264static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8265 struct wireless_dev *wdev,
8266 const void *data, int data_len)
8267{
8268 int ret;
8269
8270 cds_ssr_protect(__func__);
8271 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8272 cds_ssr_unprotect(__func__);
8273
8274 return ret;
8275}
8276
8277#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308278/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308279 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8280 * SAP is on unsafe channel.
8281 * @wiphy: wiphy structure pointer
8282 * @wdev: Wireless device structure pointer
8283 * @data: Pointer to the data received
8284 * @data_len: Length of @data
8285 *
8286 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8287 * driver.
8288 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8289 * will initiate restart of sap.
8290 *
8291 * Return: 0 on success; errno on failure
8292 */
8293static int
8294__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8295 struct wireless_dev *wdev,
8296 const void *data, int data_len)
8297{
8298 struct net_device *ndev = wdev->netdev;
8299 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8300 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8301 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8302 uint8_t config_channel = 0;
8303 hdd_ap_ctx_t *ap_ctx;
8304 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308305 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308306
8307 ENTER();
8308
8309 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008310 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308311 return -EINVAL;
8312 }
8313
8314 ret = wlan_hdd_validate_context(hdd_ctx);
8315 if (0 != ret)
8316 return -EINVAL;
8317
8318 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8319 data, data_len,
8320 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008321 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308322 return -EINVAL;
8323 }
8324
8325 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8326 if (!test_bit(SOFTAP_BSS_STARTED,
8327 &hostapd_adapter->event_flags)) {
8328 hdd_err("SAP is not started yet. Restart sap will be invalid");
8329 return -EINVAL;
8330 }
8331
8332 config_channel =
8333 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8334
8335 if (!((IS_24G_CH(config_channel)) ||
8336 (IS_5G_CH(config_channel)))) {
8337 hdd_err("Channel %d is not valid to restart SAP",
8338 config_channel);
8339 return -ENOTSUPP;
8340 }
8341
8342 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8343 ap_ctx->sapConfig.channel = config_channel;
8344 ap_ctx->sapConfig.ch_params.ch_width =
8345 ap_ctx->sapConfig.ch_width_orig;
8346
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008347 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8348 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308349 ap_ctx->sapConfig.sec_ch,
8350 &ap_ctx->sapConfig.ch_params);
8351
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008352 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308353 }
8354
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308355 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8356 uint32_t freq_len, i;
8357 uint32_t *freq;
8358 uint8_t chans[QDF_MAX_NUM_CHAN];
8359
8360 hdd_debug("setting mandatory freq/chan list");
8361
8362 freq_len = nla_len(
8363 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8364 sizeof(uint32_t);
8365
8366 if (freq_len > QDF_MAX_NUM_CHAN) {
8367 hdd_err("insufficient space to hold channels");
8368 return -ENOMEM;
8369 }
8370
8371 freq = nla_data(
8372 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8373
8374 hdd_debug("freq_len=%d", freq_len);
8375
8376 for (i = 0; i < freq_len; i++) {
8377 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8378 hdd_debug("freq[%d]=%d", i, freq[i]);
8379 }
8380
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008381 status = policy_mgr_set_sap_mandatory_channels(
8382 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308383 if (QDF_IS_STATUS_ERROR(status))
8384 return -EINVAL;
8385 }
8386
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308387 return 0;
8388}
8389
8390/**
8391 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8392 * @wiphy: wiphy structure pointer
8393 * @wdev: Wireless device structure pointer
8394 * @data: Pointer to the data received
8395 * @data_len: Length of @data
8396 *
8397 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8398 * driver.
8399 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8400 * will initiate restart of sap.
8401 *
8402 * Return: 0 on success; errno on failure
8403 */
8404static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8405 struct wireless_dev *wdev,
8406 const void *data, int data_len)
8407{
8408 int ret;
8409
8410 cds_ssr_protect(__func__);
8411 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8412 wdev, data, data_len);
8413 cds_ssr_unprotect(__func__);
8414
8415 return ret;
8416}
8417
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308418#undef BPF_INVALID
8419#undef BPF_SET_RESET
8420#undef BPF_VERSION
8421#undef BPF_ID
8422#undef BPF_PACKET_SIZE
8423#undef BPF_CURRENT_OFFSET
8424#undef BPF_PROGRAM
8425#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308426
8427/**
8428 * define short names for the global vendor params
8429 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8430 */
8431#define PARAM_TOTAL_CMD_EVENT_WAKE \
8432 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8433#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8434 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8435#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8436 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8437#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8438 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8439#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8440 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8441#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8442 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8443#define PARAM_TOTAL_RX_DATA_WAKE \
8444 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8445#define PARAM_RX_UNICAST_CNT \
8446 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8447#define PARAM_RX_MULTICAST_CNT \
8448 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8449#define PARAM_RX_BROADCAST_CNT \
8450 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8451#define PARAM_ICMP_PKT \
8452 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8453#define PARAM_ICMP6_PKT \
8454 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8455#define PARAM_ICMP6_RA \
8456 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8457#define PARAM_ICMP6_NA \
8458 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8459#define PARAM_ICMP6_NS \
8460 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8461#define PARAM_ICMP4_RX_MULTICAST_CNT \
8462 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8463#define PARAM_ICMP6_RX_MULTICAST_CNT \
8464 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8465#define PARAM_OTHER_RX_MULTICAST_CNT \
8466 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308467#define PARAM_RSSI_BREACH_CNT \
8468 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8469#define PARAM_LOW_RSSI_CNT \
8470 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8471#define PARAM_GSCAN_CNT \
8472 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8473#define PARAM_PNO_COMPLETE_CNT \
8474 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8475#define PARAM_PNO_MATCH_CNT \
8476 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8477
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308478
8479
8480/**
8481 * hdd_send_wakelock_stats() - API to send wakelock stats
8482 * @ctx: context to be passed to callback
8483 * @data: data passed to callback
8484 *
8485 * This function is used to send wake lock stats to HAL layer
8486 *
8487 * Return: 0 on success, error number otherwise.
8488 */
8489static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8490 const struct sir_wake_lock_stats *data)
8491{
8492 struct sk_buff *skb;
8493 uint32_t nl_buf_len;
8494 uint32_t total_rx_data_wake, rx_multicast_cnt;
8495 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308496 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308497
8498 ENTER();
8499
8500 nl_buf_len = NLMSG_HDRLEN;
8501 nl_buf_len +=
8502 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8503 (NLMSG_HDRLEN + sizeof(uint32_t));
8504
8505 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8506
8507 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008508 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308509 return -ENOMEM;
8510 }
8511
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008512 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308513 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008514 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308515 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008516 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308517 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008518 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308519 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008520 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308521 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008522 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308523 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008524 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308525 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008526 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8527 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308528 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008529 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308530 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008531 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308532 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008533 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308534 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008535 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308536 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008537 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308538 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308539
8540 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308541 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308542
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308543 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308544 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308545
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308546 rx_multicast_cnt =
8547 data->wow_ipv4_mcast_wake_up_count +
8548 ipv6_rx_multicast_addr_cnt;
8549
8550 total_rx_data_wake =
8551 data->wow_ucast_wake_up_count +
8552 data->wow_bcast_wake_up_count +
8553 rx_multicast_cnt;
8554
8555 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8556 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8557 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8558 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8559 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8560 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8561 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8562 total_rx_data_wake) ||
8563 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8564 data->wow_ucast_wake_up_count) ||
8565 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8566 rx_multicast_cnt) ||
8567 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8568 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308569 nla_put_u32(skb, PARAM_ICMP_PKT,
8570 data->wow_icmpv4_count) ||
8571 nla_put_u32(skb, PARAM_ICMP6_PKT,
8572 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308573 nla_put_u32(skb, PARAM_ICMP6_RA,
8574 data->wow_ipv6_mcast_ra_stats) ||
8575 nla_put_u32(skb, PARAM_ICMP6_NA,
8576 data->wow_ipv6_mcast_na_stats) ||
8577 nla_put_u32(skb, PARAM_ICMP6_NS,
8578 data->wow_ipv6_mcast_ns_stats) ||
8579 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8580 data->wow_ipv4_mcast_wake_up_count) ||
8581 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8582 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308583 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8584 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8585 data->wow_rssi_breach_wake_up_count) ||
8586 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8587 data->wow_low_rssi_wake_up_count) ||
8588 nla_put_u32(skb, PARAM_GSCAN_CNT,
8589 data->wow_gscan_wake_up_count) ||
8590 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8591 data->wow_pno_complete_wake_up_count) ||
8592 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8593 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008594 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308595 goto nla_put_failure;
8596 }
8597
8598 cfg80211_vendor_cmd_reply(skb);
8599
8600 EXIT();
8601 return 0;
8602
8603nla_put_failure:
8604 kfree_skb(skb);
8605 return -EINVAL;
8606}
8607
8608/**
8609 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8610 * @wiphy: wiphy pointer
8611 * @wdev: pointer to struct wireless_dev
8612 * @data: pointer to incoming NL vendor data
8613 * @data_len: length of @data
8614 *
8615 * This function parses the incoming NL vendor command data attributes and
8616 * invokes the SME Api and blocks on a completion variable.
8617 * WMA copies required data and invokes callback
8618 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8619 *
8620 * Return: 0 on success; error number otherwise.
8621 */
8622static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8623 struct wireless_dev *wdev,
8624 const void *data,
8625 int data_len)
8626{
8627 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8628 int status, ret;
8629 struct sir_wake_lock_stats wake_lock_stats;
8630 QDF_STATUS qdf_status;
8631
8632 ENTER();
8633
8634 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008635 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308636 return -EINVAL;
8637 }
8638
8639 status = wlan_hdd_validate_context(hdd_ctx);
8640 if (0 != status)
8641 return -EINVAL;
8642
8643 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8644 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008645 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308646 return -EINVAL;
8647 }
8648
8649 ret = hdd_send_wakelock_stats(hdd_ctx,
8650 &wake_lock_stats);
8651 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008652 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308653
8654 EXIT();
8655 return ret;
8656}
8657
8658/**
8659 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8660 * @wiphy: wiphy pointer
8661 * @wdev: pointer to struct wireless_dev
8662 * @data: pointer to incoming NL vendor data
8663 * @data_len: length of @data
8664 *
8665 * This function parses the incoming NL vendor command data attributes and
8666 * invokes the SME Api and blocks on a completion variable.
8667 * WMA copies required data and invokes callback
8668 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8669 *
8670 * Return: 0 on success; error number otherwise.
8671 */
8672static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8673 struct wireless_dev *wdev,
8674 const void *data, int data_len)
8675{
8676 int ret;
8677
8678 cds_ssr_protect(__func__);
8679 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8680 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008681 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308682
8683 return ret;
8684}
8685
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308686/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308687 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8688 * @wiphy: wiphy structure pointer
8689 * @wdev: Wireless device structure pointer
8690 * @data: Pointer to the data received
8691 * @data_len: Length of @data
8692 *
8693 * This function reads wmi max bus size and fill in the skb with
8694 * NL attributes and send up the NL event.
8695 * Return: 0 on success; errno on failure
8696 */
8697static int
8698__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8699 struct wireless_dev *wdev,
8700 const void *data, int data_len)
8701{
8702 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8703 int ret_val;
8704 struct sk_buff *skb;
8705 uint32_t nl_buf_len;
8706
8707 ENTER();
8708
8709 ret_val = wlan_hdd_validate_context(hdd_ctx);
8710 if (ret_val)
8711 return ret_val;
8712
8713 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8714 hdd_err("Command not allowed in FTM mode");
8715 return -EINVAL;
8716 }
8717
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008718 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308719
8720 nl_buf_len = NLMSG_HDRLEN;
8721 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8722
8723 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8724 if (!skb) {
8725 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8726 return -ENOMEM;
8727 }
8728
8729 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8730 hdd_ctx->wmi_max_len)) {
8731 hdd_err("nla put failure");
8732 goto nla_put_failure;
8733 }
8734
8735 cfg80211_vendor_cmd_reply(skb);
8736
8737 EXIT();
8738
8739 return 0;
8740
8741nla_put_failure:
8742 kfree_skb(skb);
8743 return -EINVAL;
8744}
8745
8746/**
8747 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8748 * @wiphy: wiphy structure pointer
8749 * @wdev: Wireless device structure pointer
8750 * @data: Pointer to the data received
8751 * @data_len: Length of @data
8752 *
8753 * Return: 0 on success; errno on failure
8754 */
8755static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8756 struct wireless_dev *wdev,
8757 const void *data, int data_len)
8758{
8759 int ret;
8760
8761 cds_ssr_protect(__func__);
8762 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8763 cds_ssr_unprotect(__func__);
8764
8765 return ret;
8766}
8767
8768/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308769 *__wlan_hdd_cfg80211_setband() - set band
8770 * @wiphy: Pointer to wireless phy
8771 * @wdev: Pointer to wireless device
8772 * @data: Pointer to data
8773 * @data_len: Length of @data
8774 *
8775 * Return: 0 on success, negative errno on failure
8776 */
8777static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8778 struct wireless_dev *wdev,
8779 const void *data, int data_len)
8780{
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308781 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008782 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308783 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8784 int ret;
8785 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8786 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8787
8788 ENTER();
8789
8790 ret = wlan_hdd_validate_context(hdd_ctx);
8791 if (ret)
8792 return ret;
8793
8794 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8795 hdd_err(FL("Invalid ATTR"));
8796 return -EINVAL;
8797 }
8798
8799 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8800 hdd_err(FL("attr SETBAND_VALUE failed"));
8801 return -EINVAL;
8802 }
8803
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008804 ret = hdd_reg_set_band(dev,
8805 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308806
8807 EXIT();
8808 return ret;
8809}
8810
8811/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308812 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8813 * @adapter: hdd adapter
8814 * @channel: channel number
8815 *
8816 * return: QDF status based on success or failure
8817 */
8818static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8819 int channel, int chan_bw)
8820{
8821 if (QDF_STATUS_SUCCESS !=
8822 wlan_hdd_validate_operation_channel(adapter, channel))
8823 return QDF_STATUS_E_FAILURE;
8824 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8825 channel,
8826 PHY_SINGLE_CHANNEL_CENTERED))) {
8827 hdd_notice("channel %d is in nol", channel);
8828 return -EINVAL;
8829 }
8830
8831 if ((wlansap_is_channel_leaking_in_nol(
8832 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8833 channel, chan_bw))) {
8834 hdd_notice("channel %d is leaking in nol", channel);
8835 return -EINVAL;
8836 }
8837
8838 return 0;
8839
8840}
8841
Kapil Gupta8878ad92017-02-13 11:56:04 +05308842static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8843 tsap_Config_t *sap_config,
8844 struct hdd_vendor_chan_info *channel_list)
8845{
8846 sap_config->channel = channel_list->pri_ch;
8847
8848 sap_config->ch_params.center_freq_seg0 =
8849 channel_list->vht_seg0_center_ch;
8850 sap_config->ch_params.center_freq_seg1 =
8851 channel_list->vht_seg1_center_ch;
8852
8853 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8854 sap_config->ch_params.ch_width = channel_list->chan_width;
8855 if (sap_config->channel >= 36)
8856 sap_config->ch_width_orig =
8857 hdd_ctx->config->vhtChannelWidth;
8858 else
8859 sap_config->ch_width_orig =
8860 hdd_ctx->config->nChannelBondingMode24GHz ?
8861 eHT_CHANNEL_WIDTH_40MHZ :
8862 eHT_CHANNEL_WIDTH_20MHZ;
8863
8864 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8865 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8866 sap_config->acs_cfg.vht_seg0_center_ch =
8867 channel_list->vht_seg0_center_ch;
8868 sap_config->acs_cfg.vht_seg1_center_ch =
8869 channel_list->vht_seg1_center_ch;
8870 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8871}
8872
8873static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8874 uint8_t channel_cnt,
8875 struct hdd_vendor_chan_info *channel_list)
8876{
8877 tsap_Config_t *sap_config;
8878 hdd_ap_ctx_t *hdd_ap_ctx;
8879 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8880 QDF_STATUS status = QDF_STATUS_SUCCESS;
8881
8882 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8883 sap_config = &adapter->sessionCtx.ap.sapConfig;
8884
8885 if (QDF_TIMER_STATE_RUNNING ==
8886 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8887 ap.vendor_acs_timer)) {
8888 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8889 }
8890
8891 if (channel_list && channel_list->pri_ch == 0) {
8892 /* Check mode, set default channel */
8893 channel_list->pri_ch = 6;
8894 /*
8895 * sap_select_default_oper_chan(hdd_ctx->hHal,
8896 * sap_config->acs_cfg.hw_mode);
8897 */
8898 }
8899
8900 switch (reason) {
8901 /* SAP init case */
8902 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8903 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8904 /* Update Hostapd */
8905 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8906 break;
8907
8908 /* DFS detected on current channel */
8909 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8910 wlan_sap_update_next_channel(
8911 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8912 channel_list->pri_ch,
8913 channel_list->chan_width);
8914 status = sme_update_new_channel_event(
8915 WLAN_HDD_GET_HAL_CTX(adapter),
8916 adapter->sessionId);
8917 break;
8918
8919 /* LTE coex event on current channel */
8920 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8921 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8922 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8923 hdd_ap_ctx->sapConfig.ch_width_orig =
8924 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008925 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308926 break;
8927
8928 default:
8929 hdd_info("invalid reason for timer invoke");
8930 }
8931 qdf_mem_free(channel_list);
8932 EXIT();
8933 return status;
8934}
8935
8936/**
8937 * Define short name for vendor channel set config
8938 */
8939#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8940#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8941#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8942#define SET_CHAN_PRIMARY_CHANNEL \
8943 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8944#define SET_CHAN_SECONDARY_CHANNEL \
8945 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8946#define SET_CHAN_SEG0_CENTER_CHANNEL \
8947 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8948#define SET_CHAN_SEG1_CENTER_CHANNEL \
8949 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8950#define SET_CHAN_CHANNEL_WIDTH \
8951 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8952#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8953
8954/**
8955 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8956 * @channel_list: pointer to hdd_vendor_chan_info
8957 * @reason: channel change reason
8958 * @channel_cnt: channel count
8959 * @data: data
8960 * @data_len: data len
8961 *
8962 * Return: 0 on success, negative errno on failure
8963 */
8964static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8965 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8966 const void *data, int data_len)
8967{
8968 int rem, i = 0;
8969 struct nlattr *tb[SET_CHAN_MAX + 1];
8970 struct nlattr *tb2[SET_CHAN_MAX + 1];
8971 struct nlattr *curr_attr;
8972 struct hdd_vendor_chan_info *channel_list;
8973
8974 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8975 hdd_err("Invalid ATTR");
8976 return -EINVAL;
8977 }
8978
8979 if (tb[SET_CHAN_REASON])
8980 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8981
8982 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8983 *channel_cnt = nla_get_u8(tb[
8984 SET_CHAN_CHANNEL_COUNT]);
8985 hdd_info("channel count %d", *channel_cnt);
8986 }
8987
8988 if (!(*channel_cnt)) {
8989 hdd_err("channel count is %d", *channel_cnt);
8990 return -EINVAL;
8991 }
8992
8993 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8994 (*channel_cnt));
8995
8996 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8997 if (nla_parse(tb2,
8998 SET_CHAN_MAX,
8999 nla_data(curr_attr), nla_len(curr_attr),
9000 NULL)) {
9001 hdd_err("nla_parse failed");
9002 return -EINVAL;
9003 }
9004 /* Parse and Fetch allowed SSID list*/
9005 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
9006 channel_list[i].pri_ch =
9007 nla_get_u8(
9008 tb2[SET_CHAN_PRIMARY_CHANNEL]);
9009 }
9010 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
9011 channel_list[i].ht_sec_ch =
9012 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
9013 }
9014 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
9015 channel_list[i].vht_seg0_center_ch =
9016 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
9017 }
9018 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
9019 channel_list[i].vht_seg1_center_ch =
9020 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
9021 }
9022 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
9023 channel_list[i].chan_width =
9024 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
9025 }
9026 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
9027 i, channel_list[i].pri_ch,
9028 channel_list[i].ht_sec_ch,
9029 channel_list[i].vht_seg0_center_ch,
9030 channel_list[i].vht_seg1_center_ch,
9031 channel_list[i].chan_width);
9032 i++;
9033 if (i > *channel_cnt)
9034 break;
9035 }
9036 *chan_list_ptr = channel_list;
9037
9038 return 0;
9039}
9040
9041/**
9042 * Undef short names for vendor set channel configuration
9043 */
9044#undef SET_CHAN_REASON
9045#undef SET_CHAN_CHANNEL_COUNT
9046#undef SET_CHAN_CHAN_LIST
9047#undef SET_CHAN_PRIMARY_CHANNEL
9048#undef SET_CHAN_SECONDARY_CHANNEL
9049#undef SET_CHAN_SEG0_CENTER_CHANNEL
9050#undef SET_CHAN_SEG1_CENTER_CHANNEL
9051#undef SET_CHAN_CHANNEL_WIDTH
9052#undef SET_CHAN_MAX
9053
9054/**
9055 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9056 * @wiphy: Pointer to wireless phy
9057 * @wdev: Pointer to wireless device
9058 * @data: Pointer to data
9059 * @data_len: Length of @data
9060 *
9061 * Return: 0 on success, negative errno on failure
9062 */
9063static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9064 struct wireless_dev *wdev,
9065 const void *data, int data_len)
9066{
9067 int ret_val;
9068 QDF_STATUS qdf_status;
9069 uint8_t channel_cnt = 0, reason = -1;
9070 struct hdd_vendor_chan_info *channel_list = NULL;
9071 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
9072 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9073
9074 ENTER();
9075
9076 ret_val = wlan_hdd_validate_context(hdd_ctx);
9077 if (ret_val)
9078 return ret_val;
9079
9080 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9081 hdd_err("Command not allowed in FTM mode");
9082 return -EINVAL;
9083 }
9084
9085 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
9086 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
9087 else {
9088 hdd_err("already timeout happened for acs");
9089 return -EINVAL;
9090 }
9091
9092 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
9093 &channel_cnt, data, data_len);
9094 if (ret_val)
9095 return ret_val;
9096
9097 /* Validate channel to be set */
9098 while (channel_cnt && channel_list) {
9099 qdf_status = wlan_hdd_validate_acs_channel(adapter,
9100 channel_list->pri_ch,
9101 channel_list->chan_width);
9102 if (qdf_status == QDF_STATUS_SUCCESS)
9103 break;
9104 channel_cnt--;
9105 channel_list++;
9106 }
9107 if ((channel_cnt <= 0) || !channel_list) {
9108 hdd_err("no available channel/chanlist %p", channel_list);
9109 return -EINVAL;
9110 }
9111
9112 qdf_status = hdd_update_acs_channel(adapter, reason,
9113 channel_cnt, channel_list);
9114 return qdf_status_to_os_return(qdf_status);
9115}
9116
9117/**
9118 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9119 * @wiphy: Pointer to wireless phy
9120 * @wdev: Pointer to wireless device
9121 * @data: Pointer to data
9122 * @data_len: Length of @data
9123 *
9124 * Return: 0 on success, negative errno on failure
9125 */
9126static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9127 struct wireless_dev *wdev,
9128 const void *data, int data_len)
9129{
9130 int ret;
9131
9132 cds_ssr_protect(__func__);
9133 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
9134 data_len);
9135 cds_ssr_protect(__func__);
9136
9137 return ret;
9138}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309139
9140/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309141 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9142 * @wiphy: wiphy structure pointer
9143 * @wdev: Wireless device structure pointer
9144 * @data: Pointer to the data received
9145 * @data_len: Length of @data
9146 *
9147 * Return: 0 on success; errno on failure
9148 */
9149static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9150 struct wireless_dev *wdev,
9151 const void *data, int data_len)
9152{
9153 int ret;
9154
9155 cds_ssr_protect(__func__);
9156 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9157 cds_ssr_unprotect(__func__);
9158
9159 return ret;
9160}
9161
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009162/**
9163 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9164 * @nl80211_value: Vendor command attribute value
9165 * @wmi_value: Pointer to return converted WMI return value
9166 *
9167 * Convert NL80211 vendor command value for SAR limit set to WMI value
9168 * Return: 0 on success, -1 on invalid value
9169 */
9170static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9171 u32 *wmi_value)
9172{
9173 int ret = 0;
9174
9175 switch (nl80211_value) {
9176 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9177 *wmi_value = WMI_SAR_FEATURE_OFF;
9178 break;
9179 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9180 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9181 break;
9182 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9183 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9184 break;
9185 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9186 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9187 break;
9188 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9189 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9190 break;
9191 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9192 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9193 break;
9194 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9195 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9196 break;
9197 default:
9198 ret = -1;
9199 }
9200 return ret;
9201}
9202
9203/**
9204 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9205 * @nl80211_value: Vendor command attribute value
9206 * @wmi_value: Pointer to return converted WMI return value
9207 *
9208 * Convert NL80211 vendor command value for SAR BAND to WMI value
9209 * Return: 0 on success, -1 on invalid value
9210 */
9211static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9212{
9213 int ret = 0;
9214
9215 switch (nl80211_value) {
9216 case NL80211_BAND_2GHZ:
9217 *wmi_value = WMI_SAR_2G_ID;
9218 break;
9219 case NL80211_BAND_5GHZ:
9220 *wmi_value = WMI_SAR_5G_ID;
9221 break;
9222 default:
9223 ret = -1;
9224 }
9225 return ret;
9226}
9227
9228/**
9229 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9230 * @nl80211_value: Vendor command attribute value
9231 * @wmi_value: Pointer to return converted WMI return value
9232 *
9233 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9234 * Return: 0 on success, -1 on invalid value
9235 */
9236static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9237 u32 *wmi_value)
9238{
9239 int ret = 0;
9240
9241 switch (nl80211_value) {
9242 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9243 *wmi_value = WMI_SAR_MOD_CCK;
9244 break;
9245 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9246 *wmi_value = WMI_SAR_MOD_OFDM;
9247 break;
9248 default:
9249 ret = -1;
9250 }
9251 return ret;
9252}
9253
9254
9255/**
9256 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9257 * @wiphy: Pointer to wireless phy
9258 * @wdev: Pointer to wireless device
9259 * @data: Pointer to data
9260 * @data_len: Length of @data
9261 *
9262 * This function is used to setup Specific Absorption Rate limit specs.
9263 *
9264 * Return: 0 on success, negative errno on failure
9265 */
9266static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9267 struct wireless_dev *wdev,
9268 const void *data, int data_len)
9269{
9270 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9271 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9272 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9273 *sar_spec_list;
9274 struct sar_limit_cmd_params sar_limit_cmd = {0};
9275 int ret = -EINVAL, i = 0, rem = 0;
9276
9277 ENTER();
9278
9279 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9280 hdd_err("Command not allowed in FTM mode");
9281 return -EPERM;
9282 }
9283
9284 if (wlan_hdd_validate_context(hdd_ctx))
9285 return -EINVAL;
9286
9287 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9288 data, data_len, NULL)) {
9289 hdd_err("Invalid SAR attributes");
9290 return -EINVAL;
9291 }
9292
9293 /* Vendor command manadates all SAR Specs in single call */
9294 sar_limit_cmd.commit_limits = 1;
9295 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9296 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9297 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9298 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9299 &sar_limit_cmd.sar_enable) < 0) {
9300 hdd_err("Invalid SAR Enable attr");
9301 goto fail;
9302 }
9303 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009304 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009305
9306 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9307 sar_limit_cmd.num_limit_rows = nla_get_u32(
9308 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009309 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009310 sar_limit_cmd.num_limit_rows);
9311 }
9312 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9313 hdd_err("SAR Spec list exceed supported size");
9314 goto fail;
9315 }
9316 if (sar_limit_cmd.num_limit_rows == 0)
9317 goto send_sar_limits;
9318 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9319 struct sar_limit_cmd_row) *
9320 sar_limit_cmd.num_limit_rows);
9321 if (!sar_limit_cmd.sar_limit_row_list) {
9322 ret = -ENOMEM;
9323 goto fail;
9324 }
9325 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9326 hdd_err("Invalid SAR SPECs list");
9327 goto fail;
9328 }
9329
9330 nla_for_each_nested(sar_spec_list,
9331 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9332 if (i == sar_limit_cmd.num_limit_rows) {
9333 hdd_warn("SAR Cmd has excess SPECs in list");
9334 break;
9335 }
9336
9337 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9338 nla_data(sar_spec_list), nla_len(sar_spec_list),
9339 NULL)) {
9340 hdd_err("nla_parse failed for SAR Spec list");
9341 goto fail;
9342 }
9343 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9344 if (sar_spec[
9345 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9346 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9347 nla_get_u32(sar_spec[
9348 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9349 } else {
9350 hdd_err("SAR Spec does not have power limit value");
9351 goto fail;
9352 }
9353
9354 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9355 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9356 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9357 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9358 < 0) {
9359 hdd_err("Invalid SAR Band attr");
9360 goto fail;
9361 }
9362 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9363 WMI_SAR_BAND_ID_VALID_MASK;
9364 }
9365 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9366 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9367 nla_get_u32(sar_spec[
9368 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9369 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9370 WMI_SAR_CHAIN_ID_VALID_MASK;
9371 }
9372 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9373 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9374 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9375 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9376 < 0) {
9377 hdd_err("Invalid SAR Modulation attr");
9378 goto fail;
9379 }
9380 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9381 WMI_SAR_MOD_ID_VALID_MASK;
9382 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009383 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009384 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9385 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9386 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9387 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9388 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9389 i++;
9390 }
9391
9392 if (i < sar_limit_cmd.num_limit_rows) {
9393 hdd_warn("SAR Cmd has less SPECs in list");
9394 sar_limit_cmd.num_limit_rows = i;
9395 }
9396
9397send_sar_limits:
9398 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9399 QDF_STATUS_SUCCESS)
9400 ret = 0;
9401fail:
9402 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9403 return ret;
9404}
9405
9406/**
9407 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9408 * @wiphy: Pointer to wireless phy
9409 * @wdev: Pointer to wireless device
9410 * @data: Pointer to data
9411 * @data_len: Length of @data
9412 *
9413 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9414 *
9415 * Return: 0 on success, negative errno on failure
9416 */
9417static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9418 struct wireless_dev *wdev,
9419 const void *data,
9420 int data_len)
9421{
9422 int ret;
9423
9424 cds_ssr_protect(__func__);
9425 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9426 data_len);
9427 cds_ssr_unprotect(__func__);
9428
9429 return ret;
9430}
9431
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309432static const struct
9433nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9434 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9435 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9436 .len = QDF_MAC_ADDR_SIZE},
9437};
9438
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309439void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9440{
9441 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9442 hdd_adapter_t *adapter;
9443
9444 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9445 if (!adapter) {
9446 hdd_err("adapter NULL");
9447 return;
9448 }
9449
9450 adapter->lfr_fw_status.is_disabled = rso_status->status;
9451 complete(&adapter->lfr_fw_status.disable_lfr_event);
9452}
9453
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309454/**
9455 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9456 * @wiphy: Pointer to wireless phy
9457 * @wdev: Pointer to wireless device
9458 * @data: Pointer to data
9459 * @data_len: Length of @data
9460 *
9461 * This function is used to enable/disable roaming using vendor commands
9462 *
9463 * Return: 0 on success, negative errno on failure
9464 */
9465static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9466 struct wireless_dev *wdev,
9467 const void *data, int data_len)
9468{
9469 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9470 struct net_device *dev = wdev->netdev;
9471 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9472 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309473 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309474 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309475 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309476 unsigned long rc;
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309477 hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309478
9479 ENTER_DEV(dev);
9480
9481 ret = wlan_hdd_validate_context(hdd_ctx);
9482 if (0 != ret)
9483 return ret;
9484
9485 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9486 hdd_err("Command not allowed in FTM mode");
9487 return -EINVAL;
9488 }
9489
9490 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9491 qca_wlan_vendor_attr);
9492 if (ret) {
9493 hdd_err("Invalid ATTR");
9494 return -EINVAL;
9495 }
9496
9497 /* Parse and fetch Enable flag */
9498 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9499 hdd_err("attr enable failed");
9500 return -EINVAL;
9501 }
9502
9503 is_fast_roam_enabled = nla_get_u32(
9504 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009505 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009506 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309507
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009508 if (!adapter->fast_roaming_allowed) {
9509 hdd_err("fast roaming not allowed on %s interface",
9510 adapter->dev->name);
9511 return -EINVAL;
9512 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309513 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309514 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309515 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309516 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309517 if (qdf_status != QDF_STATUS_SUCCESS)
9518 hdd_err("sme_config_fast_roaming failed with status=%d",
9519 qdf_status);
9520 ret = qdf_status_to_os_return(qdf_status);
9521
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309522 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
9523 QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9524
9525 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309526 /*
9527 * wait only for LFR disable in fw as LFR enable
9528 * is always success
9529 */
9530 rc = wait_for_completion_timeout(
9531 &adapter->lfr_fw_status.disable_lfr_event,
9532 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9533 if (!rc) {
9534 hdd_err("Timed out waiting for RSO CMD status");
9535 return -ETIMEDOUT;
9536 }
9537
9538 if (!adapter->lfr_fw_status.is_disabled) {
9539 hdd_err("Roam disable attempt in FW fails");
9540 return -EBUSY;
9541 }
9542 }
9543
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309544 EXIT();
9545 return ret;
9546}
9547
9548/**
9549 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9550 * @wiphy: Pointer to wireless phy
9551 * @wdev: Pointer to wireless device
9552 * @data: Pointer to data
9553 * @data_len: Length of @data
9554 *
9555 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9556 *
9557 * Return: 0 on success, negative errno on failure
9558 */
9559static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9560 struct wireless_dev *wdev,
9561 const void *data, int data_len)
9562{
9563 int ret;
9564
9565 cds_ssr_protect(__func__);
9566 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9567 cds_ssr_unprotect(__func__);
9568
9569 return ret;
9570}
9571
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309572
9573void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9574 uint32_t vdev_id)
9575{
9576 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9577 int status;
9578 hdd_adapter_t *adapter = NULL;
9579 hdd_station_ctx_t *hdd_sta_ctx;
9580
9581 status = wlan_hdd_validate_context(hdd_ctx);
9582 if (status != 0)
9583 return;
9584
9585 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9586 if (adapter == NULL) {
9587 hdd_err("vdev_id %d does not exist with host", vdev_id);
9588 return;
9589 }
9590
9591 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9592 hdd_sta_ctx->conn_info.cca = congestion;
9593 hdd_info("congestion:%d", congestion);
9594}
9595
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309596static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9597 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9598 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9599 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9600 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9601};
9602
9603/**
9604 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9605 * @wiphy: Pointer to wireless phy
9606 * @wdev: Pointer to wireless device
9607 * @data: Pointer to data
9608 * @data_len: Length of @data
9609 *
9610 * Return: 0 on success, negative errno on failure
9611 */
9612static int
9613__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9614 struct wireless_dev *wdev,
9615 const void *data,
9616 int data_len)
9617{
9618 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9619 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9620 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9621 struct nlattr *apth;
9622 int rem;
9623 int ret = 1;
9624 int print_idx = -1;
9625 int module_id = -1;
9626 int bit_mask = -1;
9627 int status;
9628
9629 ENTER();
9630
9631 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9632 hdd_err("Command not allowed in FTM mode");
9633 return -EINVAL;
9634 }
9635
9636 ret = wlan_hdd_validate_context(hdd_ctx);
9637 if (ret != 0)
9638 return -EINVAL;
9639
9640 print_idx = qdf_get_pidx();
9641 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9642 hdd_err("Invalid print controle object index");
9643 return -EINVAL;
9644 }
9645
9646 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9647 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9648 hdd_err("Invalid attr");
9649 return -EINVAL;
9650 }
9651
9652 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9653 hdd_err("attr trace level param failed");
9654 return -EINVAL;
9655 }
9656
9657 nla_for_each_nested(apth,
9658 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9659 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9660 nla_data(apth), nla_len(apth), NULL)) {
9661 hdd_err("Invalid attr");
9662 return -EINVAL;
9663 }
9664
9665 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9666 hdd_err("attr Module ID failed");
9667 return -EINVAL;
9668 }
9669 module_id = nla_get_u32
9670 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9671
9672 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9673 hdd_err("attr Verbose mask failed");
9674 return -EINVAL;
9675 }
9676 bit_mask = nla_get_u32
9677 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9678
9679 status = hdd_qdf_trace_enable(module_id, bit_mask);
9680
9681 if (status != 0)
9682 hdd_err("can not set verbose mask %d for the category %d",
9683 bit_mask, module_id);
9684 }
9685
9686 EXIT();
9687 return ret;
9688}
9689
9690/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309691 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9692 * @wiphy: Pointer to wireless phy
9693 * @wdev: Pointer to wireless device
9694 * @data: Pointer to data
9695 * @data_len: Length of @data
9696 *
9697 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9698 *
9699 * Return: 0 on success, negative errno on failure
9700 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309701
9702static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9703 struct wireless_dev *wdev,
9704 const void *data,
9705 int data_len)
9706{
9707 int ret;
9708
9709 cds_ssr_protect(__func__);
9710 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9711 cds_ssr_unprotect(__func__);
9712
9713 return ret;
9714}
9715
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009716const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9717 {
9718 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9719 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9720 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309721 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009722 .doit = is_driver_dfs_capable
9723 },
9724
9725#ifdef WLAN_FEATURE_NAN
9726 {
9727 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9728 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9729 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9730 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9731 .doit = wlan_hdd_cfg80211_nan_request
9732 },
9733#endif
9734
9735#ifdef WLAN_FEATURE_STATS_EXT
9736 {
9737 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9738 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9739 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9740 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9741 .doit = wlan_hdd_cfg80211_stats_ext_request
9742 },
9743#endif
9744#ifdef FEATURE_WLAN_EXTSCAN
9745 {
9746 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9747 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9748 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9749 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9750 .doit = wlan_hdd_cfg80211_extscan_start
9751 },
9752 {
9753 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9754 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9755 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9756 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9757 .doit = wlan_hdd_cfg80211_extscan_stop
9758 },
9759 {
9760 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9761 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9762 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9763 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9764 },
9765 {
9766 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9767 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9768 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9769 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9770 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9771 },
9772 {
9773 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9774 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9775 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9776 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9777 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9778 },
9779 {
9780 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9781 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9782 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9783 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9784 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9785 },
9786 {
9787 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9788 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9789 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9790 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9791 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9792 },
9793 {
9794 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9795 .info.subcmd =
9796 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9797 .flags =
9798 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9799 WIPHY_VENDOR_CMD_NEED_RUNNING,
9800 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9801 },
9802 {
9803 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9804 .info.subcmd =
9805 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9806 .flags =
9807 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9808 WIPHY_VENDOR_CMD_NEED_RUNNING,
9809 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9810 },
9811 {
9812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9813 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9814 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9815 WIPHY_VENDOR_CMD_NEED_NETDEV |
9816 WIPHY_VENDOR_CMD_NEED_RUNNING,
9817 .doit = wlan_hdd_cfg80211_set_epno_list
9818 },
9819#endif /* FEATURE_WLAN_EXTSCAN */
9820
9821#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9822 {
9823 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9824 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9825 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9826 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9827 .doit = wlan_hdd_cfg80211_ll_stats_clear
9828 },
9829
9830 {
9831 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9832 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9833 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9834 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9835 .doit = wlan_hdd_cfg80211_ll_stats_set
9836 },
9837
9838 {
9839 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9840 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9841 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9842 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9843 .doit = wlan_hdd_cfg80211_ll_stats_get
9844 },
9845#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9846#ifdef FEATURE_WLAN_TDLS
9847 {
9848 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9849 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9850 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9851 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9852 .doit = wlan_hdd_cfg80211_exttdls_enable
9853 },
9854 {
9855 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9856 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9857 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9858 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9859 .doit = wlan_hdd_cfg80211_exttdls_disable
9860 },
9861 {
9862 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9863 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9864 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9865 .doit = wlan_hdd_cfg80211_exttdls_get_status
9866 },
9867#endif
9868 {
9869 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9870 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9871 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9872 .doit = wlan_hdd_cfg80211_get_supported_features
9873 },
9874 {
9875 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9876 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309877 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9878 WIPHY_VENDOR_CMD_NEED_NETDEV |
9879 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009880 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9881 },
9882 {
9883 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9884 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9885 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309886 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009887 },
9888 {
9889 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9890 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9891 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309892 WIPHY_VENDOR_CMD_NEED_NETDEV |
9893 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009894 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9895 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009896 {
9897 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9898 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9899 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309900 WIPHY_VENDOR_CMD_NEED_NETDEV |
9901 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -07009902 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9903 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009904 {
9905 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309906 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9907 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9908 WIPHY_VENDOR_CMD_NEED_NETDEV |
9909 WIPHY_VENDOR_CMD_NEED_RUNNING,
9910 .doit = hdd_cfg80211_get_station_cmd
9911 },
9912 {
9913 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009914 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9915 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9916 WIPHY_VENDOR_CMD_NEED_NETDEV |
9917 WIPHY_VENDOR_CMD_NEED_RUNNING,
9918 .doit = wlan_hdd_cfg80211_do_acs
9919 },
9920
9921 {
9922 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9923 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9924 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9925 WIPHY_VENDOR_CMD_NEED_NETDEV,
9926 .doit = wlan_hdd_cfg80211_get_features
9927 },
9928#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9929 {
9930 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9931 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9932 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9933 WIPHY_VENDOR_CMD_NEED_NETDEV |
9934 WIPHY_VENDOR_CMD_NEED_RUNNING,
9935 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9936 },
9937#endif
9938#ifdef FEATURE_WLAN_EXTSCAN
9939 {
9940 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9941 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9942 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9943 WIPHY_VENDOR_CMD_NEED_NETDEV |
9944 WIPHY_VENDOR_CMD_NEED_RUNNING,
9945 .doit = wlan_hdd_cfg80211_set_passpoint_list
9946 },
9947 {
9948 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9949 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9950 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9951 WIPHY_VENDOR_CMD_NEED_NETDEV |
9952 WIPHY_VENDOR_CMD_NEED_RUNNING,
9953 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9954 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009955#endif /* FEATURE_WLAN_EXTSCAN */
9956 {
9957 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9958 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9959 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9960 WIPHY_VENDOR_CMD_NEED_NETDEV,
9961 .doit = wlan_hdd_cfg80211_get_wifi_info
9962 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009963#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009964 {
9965 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9966 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9967 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9968 WIPHY_VENDOR_CMD_NEED_NETDEV |
9969 WIPHY_VENDOR_CMD_NEED_RUNNING,
9970 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9971 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009972#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009973 {
9974 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9975 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9976 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309977 WIPHY_VENDOR_CMD_NEED_NETDEV |
9978 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009979 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9980 },
9981 {
9982 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9983 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9984 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309985 WIPHY_VENDOR_CMD_NEED_NETDEV |
9986 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009987 .doit = wlan_hdd_cfg80211_wifi_logger_start
9988 },
9989 {
9990 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9991 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9992 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309993 WIPHY_VENDOR_CMD_NEED_NETDEV |
9994 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009995 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9996 },
9997 {
9998 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9999 .info.subcmd =
10000 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
10001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10002 WIPHY_VENDOR_CMD_NEED_NETDEV |
10003 WIPHY_VENDOR_CMD_NEED_RUNNING,
10004 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
10005 },
10006 {
10007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10008 .info.subcmd =
10009 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
10010 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10011 WIPHY_VENDOR_CMD_NEED_NETDEV |
10012 WIPHY_VENDOR_CMD_NEED_RUNNING,
10013 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
10014 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070010015#ifdef WLAN_FEATURE_TSF
10016 {
10017 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10018 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
10019 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10020 WIPHY_VENDOR_CMD_NEED_NETDEV |
10021 WIPHY_VENDOR_CMD_NEED_RUNNING,
10022 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
10023 },
10024#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010025#ifdef FEATURE_WLAN_TDLS
10026 {
10027 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10028 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
10029 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10030 WIPHY_VENDOR_CMD_NEED_NETDEV |
10031 WIPHY_VENDOR_CMD_NEED_RUNNING,
10032 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
10033 },
10034#endif
10035#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
10036 {
10037 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10038 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
10039 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10040 WIPHY_VENDOR_CMD_NEED_NETDEV |
10041 WIPHY_VENDOR_CMD_NEED_RUNNING,
10042 .doit = wlan_hdd_cfg80211_offloaded_packets
10043 },
10044#endif
10045 {
10046 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10047 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
10048 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10049 WIPHY_VENDOR_CMD_NEED_NETDEV |
10050 WIPHY_VENDOR_CMD_NEED_RUNNING,
10051 .doit = wlan_hdd_cfg80211_monitor_rssi
10052 },
10053 {
10054 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010055 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
10056 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10057 WIPHY_VENDOR_CMD_NEED_NETDEV |
10058 WIPHY_VENDOR_CMD_NEED_RUNNING,
10059 .doit = wlan_hdd_cfg80211_set_ns_offload
10060 },
10061 {
10062 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010063 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
10064 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10065 WIPHY_VENDOR_CMD_NEED_NETDEV |
10066 WIPHY_VENDOR_CMD_NEED_RUNNING,
10067 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
10068 },
10069#ifdef WLAN_FEATURE_MEMDUMP
10070 {
10071 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10072 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
10073 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10074 WIPHY_VENDOR_CMD_NEED_NETDEV |
10075 WIPHY_VENDOR_CMD_NEED_RUNNING,
10076 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
10077 },
10078#endif /* WLAN_FEATURE_MEMDUMP */
10079 {
10080 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10081 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
10082 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10083 WIPHY_VENDOR_CMD_NEED_NETDEV |
10084 WIPHY_VENDOR_CMD_NEED_RUNNING,
10085 .doit = wlan_hdd_cfg80211_vendor_scan
10086 },
10087
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053010088 /* Vendor abort scan */
10089 {
10090 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10091 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
10092 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10093 WIPHY_VENDOR_CMD_NEED_NETDEV |
10094 WIPHY_VENDOR_CMD_NEED_RUNNING,
10095 .doit = wlan_hdd_vendor_abort_scan
10096 },
10097
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010098 /* OCB commands */
10099 {
10100 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10101 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
10102 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10103 WIPHY_VENDOR_CMD_NEED_NETDEV |
10104 WIPHY_VENDOR_CMD_NEED_RUNNING,
10105 .doit = wlan_hdd_cfg80211_ocb_set_config
10106 },
10107 {
10108 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10109 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
10110 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10111 WIPHY_VENDOR_CMD_NEED_NETDEV |
10112 WIPHY_VENDOR_CMD_NEED_RUNNING,
10113 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
10114 },
10115 {
10116 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10117 .info.subcmd =
10118 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
10119 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10120 WIPHY_VENDOR_CMD_NEED_NETDEV |
10121 WIPHY_VENDOR_CMD_NEED_RUNNING,
10122 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
10123 },
10124 {
10125 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10126 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
10127 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10128 WIPHY_VENDOR_CMD_NEED_NETDEV |
10129 WIPHY_VENDOR_CMD_NEED_RUNNING,
10130 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
10131 },
10132 {
10133 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10134 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
10135 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10136 WIPHY_VENDOR_CMD_NEED_NETDEV |
10137 WIPHY_VENDOR_CMD_NEED_RUNNING,
10138 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
10139 },
10140 {
10141 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10142 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
10143 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10144 WIPHY_VENDOR_CMD_NEED_NETDEV |
10145 WIPHY_VENDOR_CMD_NEED_RUNNING,
10146 .doit = wlan_hdd_cfg80211_dcc_get_stats
10147 },
10148 {
10149 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10150 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
10151 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10152 WIPHY_VENDOR_CMD_NEED_NETDEV |
10153 WIPHY_VENDOR_CMD_NEED_RUNNING,
10154 .doit = wlan_hdd_cfg80211_dcc_clear_stats
10155 },
10156 {
10157 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10158 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
10159 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10160 WIPHY_VENDOR_CMD_NEED_NETDEV |
10161 WIPHY_VENDOR_CMD_NEED_RUNNING,
10162 .doit = wlan_hdd_cfg80211_dcc_update_ndl
10163 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010164 {
10165 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10166 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
10167 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10168 WIPHY_VENDOR_CMD_NEED_NETDEV |
10169 WIPHY_VENDOR_CMD_NEED_RUNNING,
10170 .doit = wlan_hdd_cfg80211_get_link_properties
10171 },
Peng Xu278d0122015-09-24 16:34:17 -070010172 {
Peng Xud2220962016-07-11 17:59:17 -070010173 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070010174 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
10175 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10176 WIPHY_VENDOR_CMD_NEED_NETDEV |
10177 WIPHY_VENDOR_CMD_NEED_RUNNING,
10178 .doit = wlan_hdd_cfg80211_set_ota_test
10179 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080010180#ifdef FEATURE_LFR_SUBNET_DETECTION
10181 {
10182 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10183 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
10184 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10185 WIPHY_VENDOR_CMD_NEED_NETDEV |
10186 WIPHY_VENDOR_CMD_NEED_RUNNING,
10187 .doit = wlan_hdd_cfg80211_set_gateway_params
10188 },
10189#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070010190 {
Peng Xud2220962016-07-11 17:59:17 -070010191 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070010192 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
10193 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10194 WIPHY_VENDOR_CMD_NEED_NETDEV |
10195 WIPHY_VENDOR_CMD_NEED_RUNNING,
10196 .doit = wlan_hdd_cfg80211_txpower_scale
10197 },
10198 {
10199 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10200 .info.subcmd =
10201 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
10202 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10203 WIPHY_VENDOR_CMD_NEED_NETDEV |
10204 WIPHY_VENDOR_CMD_NEED_RUNNING,
10205 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
10206 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010207 {
10208 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10209 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
10210 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10211 WIPHY_VENDOR_CMD_NEED_NETDEV |
10212 WIPHY_VENDOR_CMD_NEED_RUNNING,
10213 .doit = wlan_hdd_cfg80211_bpf_offload
10214 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010215 {
10216 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053010217 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
10218 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10219 WIPHY_VENDOR_CMD_NEED_NETDEV |
10220 WIPHY_VENDOR_CMD_NEED_RUNNING,
10221 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10222 },
10223 {
10224 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010225 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10226 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10227 WIPHY_VENDOR_CMD_NEED_NETDEV |
10228 WIPHY_VENDOR_CMD_NEED_RUNNING,
10229 .doit = wlan_hdd_cfg80211_sta_roam_policy
10230 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010231#ifdef FEATURE_WLAN_CH_AVOID
10232 {
10233 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10234 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10235 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10236 WIPHY_VENDOR_CMD_NEED_NETDEV |
10237 WIPHY_VENDOR_CMD_NEED_RUNNING,
10238 .doit = wlan_hdd_cfg80211_avoid_freq
10239 },
10240#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010241 {
10242 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010243 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10244 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10245 WIPHY_VENDOR_CMD_NEED_NETDEV |
10246 WIPHY_VENDOR_CMD_NEED_RUNNING,
10247 .doit = wlan_hdd_cfg80211_sap_configuration_set
10248 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010249 {
Peng Xu4225c152016-07-14 21:18:14 -070010250 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010251 .info.subcmd =
10252 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10253 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10254 WIPHY_VENDOR_CMD_NEED_NETDEV |
10255 WIPHY_VENDOR_CMD_NEED_RUNNING,
10256 .doit = wlan_hdd_cfg80211_p2p_lo_start
10257 },
10258 {
10259 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10260 .info.subcmd =
10261 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10262 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10263 WIPHY_VENDOR_CMD_NEED_NETDEV |
10264 WIPHY_VENDOR_CMD_NEED_RUNNING,
10265 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10266 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010267 {
10268 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10269 .info.subcmd =
10270 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10271 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10272 WIPHY_VENDOR_CMD_NEED_NETDEV |
10273 WIPHY_VENDOR_CMD_NEED_RUNNING,
10274 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10275 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010276#ifdef WLAN_FEATURE_NAN_DATAPATH
10277 {
10278 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10279 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10280 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10281 WIPHY_VENDOR_CMD_NEED_NETDEV |
10282 WIPHY_VENDOR_CMD_NEED_RUNNING,
10283 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10284 },
10285#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010286 {
10287 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10288 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10289 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10290 WIPHY_VENDOR_CMD_NEED_NETDEV |
10291 WIPHY_VENDOR_CMD_NEED_RUNNING,
10292 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10293 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010294 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010295 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10296 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10297 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10298 WIPHY_VENDOR_CMD_NEED_NETDEV |
10299 WIPHY_VENDOR_CMD_NEED_RUNNING,
10300 .doit = wlan_hdd_cfg80211_get_bus_size
10301 },
10302 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010303 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10304 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10305 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10306 WIPHY_VENDOR_CMD_NEED_NETDEV |
10307 WIPHY_VENDOR_CMD_NEED_RUNNING,
10308 .doit = wlan_hdd_cfg80211_update_vendor_channel
10309 },
10310 {
bingsd09dea32017-03-17 10:08:26 +080010311 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010312 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10313 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10314 WIPHY_VENDOR_CMD_NEED_NETDEV |
10315 WIPHY_VENDOR_CMD_NEED_RUNNING,
10316 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010317 },
10318 {
10319 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10320 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10321 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10322 WIPHY_VENDOR_CMD_NEED_NETDEV |
10323 WIPHY_VENDOR_CMD_NEED_RUNNING,
10324 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010325 },
10326#ifdef WLAN_FEATURE_DISA
10327 {
10328 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10329 .info.subcmd =
10330 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10331 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10332 WIPHY_VENDOR_CMD_NEED_NETDEV |
10333 WIPHY_VENDOR_CMD_NEED_RUNNING,
10334 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10335 },
10336#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010337#ifdef FEATURE_WLAN_TDLS
10338 {
10339 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10340 .info.subcmd =
10341 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10342 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10343 WIPHY_VENDOR_CMD_NEED_NETDEV |
10344 WIPHY_VENDOR_CMD_NEED_RUNNING,
10345 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010346 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010347#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010348 {
10349 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10350 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10351 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10352 WIPHY_VENDOR_CMD_NEED_RUNNING,
10353 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10354 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010355 {
10356 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10357 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10358 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10359 WIPHY_VENDOR_CMD_NEED_NETDEV |
10360 WIPHY_VENDOR_CMD_NEED_RUNNING,
10361 .doit = wlan_hdd_cfg80211_set_trace_level
10362 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080010363 {
10364 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10365 .info.subcmd =
10366 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
10367 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10368 WIPHY_VENDOR_CMD_NEED_NETDEV |
10369 WIPHY_VENDOR_CMD_NEED_RUNNING,
10370 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
10371 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010372
Paul Zhang3a210c52016-12-08 10:18:12 +080010373#ifdef WLAN_UMAC_CONVERGENCE
10374 COMMON_VENDOR_COMMANDS
10375#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010376 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010377};
10378
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010379#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10380 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10381 defined(FEATURE_WLAN_SCAN_PNO)
10382/**
10383 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10384 * @wiphy: pointer to wiphy
10385 * @config: pointer to config
10386 *
10387 * Return: None
10388 */
10389static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10390 struct hdd_config *config)
10391{
10392 if (config->configPNOScanSupport) {
10393 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010394 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10395 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010396 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010397 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010398 if (config->max_sched_scan_plan_interval)
10399 wiphy->max_sched_scan_plan_interval =
10400 config->max_sched_scan_plan_interval;
10401 if (config->max_sched_scan_plan_iterations)
10402 wiphy->max_sched_scan_plan_iterations =
10403 config->max_sched_scan_plan_iterations;
10404 }
10405}
10406#else
10407static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10408 struct hdd_config *config)
10409{
10410}
10411#endif
10412
10413
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010414/**
10415 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10416 * @priv_size: Size of the hdd context.
10417 *
10418 * Allocate wiphy context and hdd context.
10419 *
10420 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010421 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010422hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010423{
10424 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010425 hdd_context_t *hdd_ctx;
10426
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010427 ENTER();
10428
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010429 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10430
10431 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010432 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010433 return NULL;
10434 }
10435
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010436 hdd_ctx = wiphy_priv(wiphy);
10437
10438 hdd_ctx->wiphy = wiphy;
10439
10440 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010441}
10442
10443/*
10444 * FUNCTION: wlan_hdd_cfg80211_update_band
10445 * This function is called from the supplicant through a
10446 * private ioctl to change the band value
10447 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010448int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10449 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010450{
10451 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010452 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010453
10454 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010455 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010456
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010457 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010458 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010459
10460 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10461 struct ieee80211_supported_band *band = wiphy->bands[i];
10462
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010463 channelEnabledState = wlan_reg_get_channel_state(
10464 hdd_ctx->hdd_pdev,
10465 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010466
Dustin Browna30892e2016-10-12 17:28:36 -070010467 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010468 /* 5G only */
10469#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10470 /* Enable Social channels for P2P */
10471 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10472 (band->channels[j].center_freq)
10473 && CHANNEL_STATE_ENABLE ==
10474 channelEnabledState)
10475 band->channels[j].flags &=
10476 ~IEEE80211_CHAN_DISABLED;
10477 else
10478#endif
10479 band->channels[j].flags |=
10480 IEEE80211_CHAN_DISABLED;
10481 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010482 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010483 eCSR_BAND_24 == eBand) {
10484 /* 2G only */
10485 band->channels[j].flags |=
10486 IEEE80211_CHAN_DISABLED;
10487 continue;
10488 }
10489
Amar Singhal6842e8f2016-02-23 16:30:32 -080010490 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010491 band->channels[j].flags &=
10492 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010493 }
10494 }
10495 return 0;
10496}
10497
Peng Xuacfdda12017-02-06 16:15:38 -080010498#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010499/*
10500 * FUNCTION: wlan_hdd_cfg80211_init
10501 * This function is called by hdd_wlan_startup()
10502 * during initialization.
10503 * This function is used to initialize and register wiphy structure.
10504 */
10505int wlan_hdd_cfg80211_init(struct device *dev,
10506 struct wiphy *wiphy, struct hdd_config *pCfg)
10507{
10508 int i, j;
10509 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10510
10511 ENTER();
10512
10513 /* Now bind the underlying wlan device with wiphy */
10514 set_wiphy_dev(wiphy, dev);
10515
10516 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10517
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010518 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10519 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10520 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10521#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10522 | WIPHY_FLAG_4ADDR_STATION
10523#endif
10524 | WIPHY_FLAG_OFFCHAN_TX;
10525
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010526#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10527 wiphy->wowlan = &wowlan_support_cfg80211_init;
10528#else
10529 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10530 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10531 wiphy->wowlan.pattern_min_len = 1;
10532 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10533#endif
10534
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010535 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010536#ifdef FEATURE_WLAN_ESE
10537 || pCfg->isEseIniFeatureEnabled
10538#endif
10539 ) {
10540 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10541 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010542#ifdef FEATURE_WLAN_TDLS
10543 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10544 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10545#endif
10546
10547 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10548
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010549#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10550 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10551#endif
10552
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010553 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010554
10555#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010556 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010557#endif
10558
10559 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010560 * driver can still register regulatory callback and
10561 * it will get regulatory settings in wiphy->band[], but
10562 * driver need to determine what to do with both
10563 * regulatory settings
10564 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010566#if defined QCA_WIFI_FTM
10567}
10568#endif
10569
10570 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10571
10572 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10573
10574 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10575
Arun Khandavallifae92942016-08-01 13:31:08 +053010576 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10577 | BIT(NL80211_IFTYPE_ADHOC)
10578 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10579 | BIT(NL80211_IFTYPE_P2P_GO)
10580 | BIT(NL80211_IFTYPE_AP)
10581 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010582
Arun Khandavallifae92942016-08-01 13:31:08 +053010583 if (pCfg->advertiseConcurrentOperation) {
10584 if (pCfg->enableMCC) {
10585 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010586
Arun Khandavallifae92942016-08-01 13:31:08 +053010587 for (i = 0;
10588 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10589 i++) {
10590 if (!pCfg->allowMCCGODiffBI)
10591 wlan_hdd_iface_combination[i].
10592 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010593 }
10594 }
10595 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010596 ARRAY_SIZE(wlan_hdd_iface_combination);
10597 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010598 }
10599
10600 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010601 * on ini values
10602 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010603 if (!pCfg->ShortGI20MhzEnable) {
10604 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10605 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010606 }
10607
10608 if (!pCfg->ShortGI40MhzEnable) {
10609 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10610 }
10611
10612 if (!pCfg->nChannelBondingMode5GHz) {
10613 wlan_hdd_band_5_ghz.ht_cap.cap &=
10614 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10615 }
10616
Abhishek Singhf512bf32016-05-04 16:47:46 +053010617 /*
10618 * In case of static linked driver at the time of driver unload,
10619 * module exit doesn't happens. Module cleanup helps in cleaning
10620 * of static memory.
10621 * If driver load happens statically, at the time of driver unload,
10622 * wiphy flags don't get reset because of static memory.
10623 * It's better not to store channel in static memory.
10624 */
Dustin Browna30892e2016-10-12 17:28:36 -070010625 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10626 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010627 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010628 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010629 hdd_err("Not enough memory to allocate channels");
10630 return -ENOMEM;
10631 }
Dustin Browna30892e2016-10-12 17:28:36 -070010632 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010633 &hdd_channels_2_4_ghz[0],
10634 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010635 if ((hdd_is_5g_supported(pHddCtx)) &&
10636 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10637 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10638 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10639 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010640 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10641 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010642 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010643 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010644 hdd_err("Not enough memory to allocate channels");
10645 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010646 bands[NL80211_BAND_2GHZ]->channels);
10647 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010648 return -ENOMEM;
10649 }
Dustin Browna30892e2016-10-12 17:28:36 -070010650 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010651 &hdd_channels_5_ghz[0],
10652 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010653 }
10654
Dustin Browna30892e2016-10-12 17:28:36 -070010655 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010656
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010657 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010658 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010659
10660 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10661 struct ieee80211_supported_band *band = wiphy->bands[i];
10662
Dustin Browna30892e2016-10-12 17:28:36 -070010663 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010664 eCSR_BAND_5G == pCfg->nBandCapability) {
10665 /* 5G only */
10666#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10667 /* Enable social channels for P2P */
10668 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10669 (band->channels[j].center_freq))
10670 band->channels[j].flags &=
10671 ~IEEE80211_CHAN_DISABLED;
10672 else
10673#endif
10674 band->channels[j].flags |=
10675 IEEE80211_CHAN_DISABLED;
10676 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010677 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010678 eCSR_BAND_24 == pCfg->nBandCapability) {
10679 /* 2G only */
10680 band->channels[j].flags |=
10681 IEEE80211_CHAN_DISABLED;
10682 continue;
10683 }
10684 }
10685 }
10686 /*Initialise the supported cipher suite details */
10687 wiphy->cipher_suites = hdd_cipher_suites;
10688 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10689
10690 /*signal strength in mBm (100*dBm) */
10691 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10692 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10693
Anurag Chouhan6d760662016-02-20 16:05:43 +053010694 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010695 wiphy->n_vendor_commands =
10696 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10697 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10698
10699 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10700 wiphy->n_vendor_events =
10701 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10702 }
10703
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704 if (pCfg->enableDFSMasterCap) {
10705 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10706 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010707
10708 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10709
10710#ifdef QCA_HT_2040_COEX
10711 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10712#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010713 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010714
10715#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10716 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10717 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10718 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10719 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10720#endif
10721
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010722 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010723 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010724
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010725 EXIT();
10726 return 0;
10727}
10728
Abhishek Singhf512bf32016-05-04 16:47:46 +053010729/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010730 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10731 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010732 *
10733 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010734 * memory allocated in wlan_hdd_cfg80211_init also
10735 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010736 *
10737 * Return: void
10738 */
10739void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10740{
10741 int i;
10742
Dustin Browna30892e2016-10-12 17:28:36 -070010743 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010744 if (NULL != wiphy->bands[i] &&
10745 (NULL != wiphy->bands[i]->channels)) {
10746 qdf_mem_free(wiphy->bands[i]->channels);
10747 wiphy->bands[i]->channels = NULL;
10748 }
10749 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010750
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010751 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010752}
10753
Yingying Tang80e15f32016-09-27 18:23:01 +080010754/**
10755 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10756 * @hdd_ctx: HDD context
10757 *
10758 * this function will update capabilities for supported bands
10759 *
10760 * Return: void
10761 */
10762static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10763{
10764 uint32_t val32;
10765 uint16_t val16;
10766 tSirMacHTCapabilityInfo *ht_cap_info;
10767 QDF_STATUS status;
10768
10769 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10770 if (QDF_STATUS_SUCCESS != status) {
10771 hdd_err("could not get HT capability info");
10772 val32 = 0;
10773 }
10774 val16 = (uint16_t)val32;
10775 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10776
10777 if (ht_cap_info->txSTBC == true) {
10778 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10779 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10780 IEEE80211_HT_CAP_TX_STBC;
10781 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10782 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10783 IEEE80211_HT_CAP_TX_STBC;
10784 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010785
10786 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10787 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10788 vht_cap.vht_supported = 0;
10789 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10790 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10791 vht_cap.vht_supported = 0;
10792 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10793 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010794}
10795
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010796/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010797 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010798 * initialization. In wlan_hdd_cfg80211_init, only the
10799 * default values will be initialized. The final initialization
10800 * of all required members can be done here.
10801 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010802void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010803{
Yingying Tang80e15f32016-09-27 18:23:01 +080010804 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10805
10806 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010807}
10808
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010809/**
10810 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10811 * @cfg: hdd cfg
10812 *
10813 * this function update 11n mode in hdd cfg
10814 *
10815 * Return: void
10816 */
10817void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10818{
10819 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010820 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010821 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010822 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010823 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10824 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10825 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10826 cfg->sap_p2p_11ac_override = 0;
10827 }
10828 }
10829}
10830
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831/* In this function we are registering wiphy. */
10832int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10833{
10834 ENTER();
10835 /* Register our wiphy dev with cfg80211 */
10836 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010837 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010838 return -EIO;
10839 }
10840
10841 EXIT();
10842 return 0;
10843}
10844
10845/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010846 * HDD function to update wiphy capability based on target offload status.
10847 *
10848 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10849 * capability even before downloading firmware to the target. In discrete
10850 * case, host will get know certain offload capability (say sched_scan
10851 * caps) only after downloading firmware to the target and target boots up.
10852 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10853 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010854 */
10855void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10856{
10857#ifdef FEATURE_WLAN_SCAN_PNO
10858 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10859 struct hdd_config *pCfg = pHddCtx->config;
10860
10861 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10862 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010863 * have PNO support.
10864 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010865 if (!pCfg->PnoOffload) {
10866 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10867 wiphy->max_sched_scan_ssids = 0;
10868 wiphy->max_match_sets = 0;
10869 wiphy->max_sched_scan_ie_len = 0;
10870 }
10871#endif
10872}
10873
10874/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010875#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10876
Wu Gao84d120c2017-03-24 18:46:00 +080010877void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10878{
10879 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10880 /* Register for all P2P action, public action etc frames */
10881 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10882
10883 ENTER();
10884
10885 /* Register frame indication call back */
10886 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10887
10888 /* Register for p2p ack indication */
10889 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10890
10891 /* Right now we are registering these frame when driver is getting
10892 * initialized. Once we will move to 2.6.37 kernel, in which we have
10893 * frame register ops, we will move this code as a part of that
10894 */
10895
10896 /* GAS Initial Request */
10897 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10898 (uint8_t *) GAS_INITIAL_REQ,
10899 GAS_INITIAL_REQ_SIZE);
10900
10901 /* GAS Initial Response */
10902 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10903 (uint8_t *) GAS_INITIAL_RSP,
10904 GAS_INITIAL_RSP_SIZE);
10905
10906 /* GAS Comeback Request */
10907 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10908 (uint8_t *) GAS_COMEBACK_REQ,
10909 GAS_COMEBACK_REQ_SIZE);
10910
10911 /* GAS Comeback Response */
10912 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10913 (uint8_t *) GAS_COMEBACK_RSP,
10914 GAS_COMEBACK_RSP_SIZE);
10915
10916 /* WNM BSS Transition Request frame */
10917 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10918 (uint8_t *) WNM_BSS_ACTION_FRAME,
10919 WNM_BSS_ACTION_FRAME_SIZE);
10920
10921 /* WNM-Notification */
10922 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10923 (uint8_t *) WNM_NOTIFICATION_FRAME,
10924 WNM_NOTIFICATION_FRAME_SIZE);
10925}
10926#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010927void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10928{
10929 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10930 /* Register for all P2P action, public action etc frames */
10931 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10932
10933 ENTER();
10934
Abhishek Singh7996eb72015-12-30 17:24:02 +053010935 /* Register frame indication call back */
10936 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10937
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010938 /* Register for p2p ack indication */
10939 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10940
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010942 * initialized. Once we will move to 2.6.37 kernel, in which we have
10943 * frame register ops, we will move this code as a part of that
10944 */
10945
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010946 /* GAS Initial Request */
10947 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10948 (uint8_t *) GAS_INITIAL_REQ,
10949 GAS_INITIAL_REQ_SIZE);
10950
10951 /* GAS Initial Response */
10952 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10953 (uint8_t *) GAS_INITIAL_RSP,
10954 GAS_INITIAL_RSP_SIZE);
10955
10956 /* GAS Comeback Request */
10957 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10958 (uint8_t *) GAS_COMEBACK_REQ,
10959 GAS_COMEBACK_REQ_SIZE);
10960
10961 /* GAS Comeback Response */
10962 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10963 (uint8_t *) GAS_COMEBACK_RSP,
10964 GAS_COMEBACK_RSP_SIZE);
10965
10966 /* P2P Public Action */
10967 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10968 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10969 P2P_PUBLIC_ACTION_FRAME_SIZE);
10970
10971 /* P2P Action */
10972 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10973 (uint8_t *) P2P_ACTION_FRAME,
10974 P2P_ACTION_FRAME_SIZE);
10975
10976 /* WNM BSS Transition Request frame */
10977 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10978 (uint8_t *) WNM_BSS_ACTION_FRAME,
10979 WNM_BSS_ACTION_FRAME_SIZE);
10980
10981 /* WNM-Notification */
10982 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10983 (uint8_t *) WNM_NOTIFICATION_FRAME,
10984 WNM_NOTIFICATION_FRAME_SIZE);
10985}
Wu Gao84d120c2017-03-24 18:46:00 +080010986#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010987
10988void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10989{
10990 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10991 /* Register for all P2P action, public action etc frames */
10992 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10993
10994 ENTER();
10995
10996 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010997 * initialized. Once we will move to 2.6.37 kernel, in which we have
10998 * frame register ops, we will move this code as a part of that
10999 */
11000
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011001 /* GAS Initial Request */
11002
11003 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11004 (uint8_t *) GAS_INITIAL_REQ,
11005 GAS_INITIAL_REQ_SIZE);
11006
11007 /* GAS Initial Response */
11008 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11009 (uint8_t *) GAS_INITIAL_RSP,
11010 GAS_INITIAL_RSP_SIZE);
11011
11012 /* GAS Comeback Request */
11013 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11014 (uint8_t *) GAS_COMEBACK_REQ,
11015 GAS_COMEBACK_REQ_SIZE);
11016
11017 /* GAS Comeback Response */
11018 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11019 (uint8_t *) GAS_COMEBACK_RSP,
11020 GAS_COMEBACK_RSP_SIZE);
11021
11022 /* P2P Public Action */
11023 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11024 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11025 P2P_PUBLIC_ACTION_FRAME_SIZE);
11026
11027 /* P2P Action */
11028 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11029 (uint8_t *) P2P_ACTION_FRAME,
11030 P2P_ACTION_FRAME_SIZE);
11031
11032 /* WNM-Notification */
11033 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
11034 (uint8_t *) WNM_NOTIFICATION_FRAME,
11035 WNM_NOTIFICATION_FRAME_SIZE);
11036}
11037
11038#ifdef FEATURE_WLAN_WAPI
11039void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
11040 const uint8_t *mac_addr, const uint8_t *key,
11041 int key_Len)
11042{
11043 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11044 tCsrRoamSetKey setKey;
11045 bool isConnected = true;
11046 int status = 0;
11047 uint32_t roamId = 0xFF;
11048 uint8_t *pKeyPtr = NULL;
11049 int n = 0;
11050
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011051 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052 hdd_device_mode_to_string(pAdapter->device_mode),
11053 pAdapter->device_mode);
11054
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011055 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011056 setKey.keyId = key_index; /* Store Key ID */
11057 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
11058 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
11059 setKey.paeRole = 0; /* the PAE role */
11060 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053011061 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011062 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011063 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011064 }
11065 setKey.keyLength = key_Len;
11066 pKeyPtr = setKey.Key;
11067 memcpy(pKeyPtr, key, key_Len);
11068
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011069 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011070 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011071 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070011072 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011073
11074 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11075 if (isConnected) {
11076 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11077 pAdapter->sessionId, &setKey, &roamId);
11078 }
11079 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011080 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011081 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
11082 }
11083}
11084#endif /* FEATURE_WLAN_WAPI */
11085
11086uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
11087 uint8_t eid)
11088{
11089 int left = length;
11090 uint8_t *ptr = (uint8_t *)ies_ptr;
11091 uint8_t elem_id, elem_len;
11092
11093 while (left >= 2) {
11094 elem_id = ptr[0];
11095 elem_len = ptr[1];
11096 left -= 2;
11097 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011098 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099 eid, elem_len, left);
11100 return NULL;
11101 }
11102 if (elem_id == eid) {
11103 return ptr;
11104 }
11105
11106 left -= elem_len;
11107 ptr += (elem_len + 2);
11108 }
11109 return NULL;
11110}
11111
Krunal Soni364e0872017-05-10 21:24:34 -070011112bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
11113{
11114 uint8_t *vendor_ie;
11115
11116 if (length < 2) {
11117 hdd_debug("bss size is less than expected");
11118 return true;
11119 }
11120 if (!ies) {
11121 hdd_debug("invalid IE pointer");
11122 return true;
11123 }
11124 vendor_ie = wlan_hdd_get_vendor_oui_ie_ptr(VENDOR1_AP_OUI_TYPE,
11125 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
11126 if (vendor_ie) {
11127 hdd_debug("AP can't support immediate powersave. defer it");
11128 return false;
11129 }
11130 return true;
11131}
11132
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011133/*
11134 * FUNCTION: wlan_hdd_validate_operation_channel
11135 * called by wlan_hdd_cfg80211_start_bss() and
11136 * wlan_hdd_set_channel()
11137 * This function validates whether given channel is part of valid
11138 * channel list.
11139 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011140QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011141 int channel)
11142{
11143
11144 uint32_t num_ch = 0;
11145 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11146 u32 indx = 0;
11147 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11148 uint8_t fValidChannel = false, count = 0;
11149 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
11150
11151 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11152
11153 if (hdd_pConfig_ini->sapAllowAllChannel) {
11154 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080011155 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011156 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011157 fValidChannel = true;
11158 break;
11159 }
11160 }
11161 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011162 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011163 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011164 }
11165 } else {
11166 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
11167 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011168 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011169 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011170 }
11171 for (indx = 0; indx < num_ch; indx++) {
11172 if (channel == valid_ch[indx]) {
11173 break;
11174 }
11175 }
11176
11177 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011178 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011179 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180 }
11181 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011182 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011183
11184}
11185
11186#ifdef DHCP_SERVER_OFFLOAD
11187static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
11188{
11189 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
11190 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
11191 uint8_t numEntries = 0;
11192 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
11193 uint8_t num;
11194 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011195 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070011197 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011198 return;
11199 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011200 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
11201 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
11202 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
11203 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
11204 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
11205 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011206 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011207 goto end;
11208 }
11209 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011210 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011211 goto end;
11212 }
11213 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011214 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011215 goto end;
11216 }
11217 for (num = 0; num < numEntries; num++) {
11218 temp = srv_ip[num];
11219 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
11220 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011221 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011223 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011224 goto end;
11225 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011226 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011227end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011228 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011229 return;
11230}
11231#endif /* DHCP_SERVER_OFFLOAD */
11232
11233static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11234 struct net_device *dev,
11235 struct bss_parameters *params)
11236{
11237 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11238 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11239 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011240 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011241
11242 ENTER();
11243
Anurag Chouhan6d760662016-02-20 16:05:43 +053011244 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011245 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011246 return -EINVAL;
11247 }
11248
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011249 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11250 hdd_err("invalid session id: %d", pAdapter->sessionId);
11251 return -EINVAL;
11252 }
11253
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011254 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011255 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11256 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011257 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258 hdd_device_mode_to_string(pAdapter->device_mode),
11259 pAdapter->device_mode, params->ap_isolate);
11260
11261 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11262 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011263 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011264 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011265
Krunal Sonib4326f22016-03-10 13:05:51 -080011266 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11267 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011268 return -EOPNOTSUPP;
11269 }
11270
11271 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011272 * want to update this parameter
11273 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011274 if (-1 != params->ap_isolate) {
11275 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11276 !!params->ap_isolate;
11277
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011278 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011279 pAdapter->sessionId,
11280 pAdapter->sessionCtx.
11281 ap.
11282 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011283 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011284 ret = -EINVAL;
11285 }
11286 }
11287
11288 EXIT();
11289 return ret;
11290}
11291
Krunal Soni8c37e322016-02-03 16:08:37 -080011292/**
11293 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11294 * @ndev: pointer to net device provided by supplicant
11295 * @type: type of the interface, upper layer wanted to change
11296 *
11297 * Upper layer provides the new interface mode that needs to be changed
11298 * for given net device
11299 *
11300 * Return: success or failure in terms of integer value
11301 */
11302static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011303 enum nl80211_iftype type)
11304{
Krunal Soni8c37e322016-02-03 16:08:37 -080011305 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11306 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11307 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011308 hdd_wext_state_t *wext;
11309 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011310 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011311
11312 ENTER();
11313
Krunal Soni8c37e322016-02-03 16:08:37 -080011314 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011315 hdd_warn("ACS is in progress, don't change iface!");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011316 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011317 }
11318
11319 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011320 hdd_stop_adapter(hdd_ctx, adapter, true);
11321 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011322 wdev->iftype = type;
11323 /*Check for sub-string p2p to confirm its a p2p interface */
11324 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011325 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011326 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011327 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011328 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011329 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011330 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011331 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011332 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011333 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011334 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011335 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11336 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011337 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11338 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011340 adapter->scan_info.scanAddIE.length;
11341 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011342 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011343 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11344 wext->roamProfile.phyMode =
11345 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11346 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011347 EXIT();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011348
11349 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011350}
11351
11352static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11353 struct net_device *dev,
11354 struct bss_parameters *params)
11355{
11356 int ret;
11357
11358 cds_ssr_protect(__func__);
11359 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11360 cds_ssr_unprotect(__func__);
11361
11362 return ret;
11363}
11364
11365/* FUNCTION: wlan_hdd_change_country_code_cd
11366 * to wait for contry code completion
11367 */
11368void *wlan_hdd_change_country_code_cb(void *pAdapter)
11369{
11370 hdd_adapter_t *call_back_pAdapter = pAdapter;
11371 complete(&call_back_pAdapter->change_country_code);
11372 return NULL;
11373}
11374
Rajeev Kumar98edb772016-01-19 12:42:19 -080011375/**
11376 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11377 * @wiphy: Pointer to the wiphy structure
11378 * @ndev: Pointer to the net device
11379 * @type: Interface type
11380 * @flags: Flags for change interface
11381 * @params: Pointer to change interface parameters
11382 *
11383 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011384 */
11385static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11386 struct net_device *ndev,
11387 enum nl80211_iftype type,
11388 u32 *flags,
11389 struct vif_params *params)
11390{
11391 struct wireless_dev *wdev;
11392 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11393 hdd_context_t *pHddCtx;
11394 tCsrRoamProfile *pRoamProfile = NULL;
11395 eCsrRoamBssType LastBSSType;
11396 struct hdd_config *pConfig = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011397 int status;
11398
11399 ENTER();
11400
Anurag Chouhan6d760662016-02-20 16:05:43 +053011401 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011402 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011403 return -EINVAL;
11404 }
11405
11406 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11407 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011408 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011409 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011410
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011411 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011412 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11413 pAdapter->sessionId, type));
11414
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011415 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011416 pAdapter->device_mode, type);
11417
Arun Khandavallifae92942016-08-01 13:31:08 +053011418 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11419 if (status) {
11420 hdd_err("Failed to start modules");
11421 return -EINVAL;
11422 }
11423
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011424 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011425 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11426 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011427 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011428 return -EINVAL;
11429 }
11430
11431 pConfig = pHddCtx->config;
11432 wdev = ndev->ieee80211_ptr;
11433
11434 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011435 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11436 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011437
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011438 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011439 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011440 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11441 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11442 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11443 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011444 hdd_wext_state_t *pWextState =
11445 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11446
11447 pRoamProfile = &pWextState->roamProfile;
11448 LastBSSType = pRoamProfile->BSSType;
11449
11450 switch (type) {
11451 case NL80211_IFTYPE_STATION:
11452 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011453 case NL80211_IFTYPE_ADHOC:
11454 if (type == NL80211_IFTYPE_ADHOC) {
11455 wlan_hdd_tdls_exit(pAdapter);
11456 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011457 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011458 }
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011459 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
Krunal Soni8c37e322016-02-03 16:08:37 -080011460 type);
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011461 if (status) {
11462 hdd_err("Failed to change iface to new mode:%d status %d",
11463 type, status);
11464 return status;
11465 }
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011466 if (hdd_start_adapter(pAdapter)) {
11467 hdd_err("Failed to start adapter :%d",
11468 pAdapter->device_mode);
11469 return -EINVAL;
11470 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011471 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011472 case NL80211_IFTYPE_AP:
11473 case NL80211_IFTYPE_P2P_GO:
11474 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011475 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011476 (type ==
11477 NL80211_IFTYPE_AP) ? "SoftAP" :
11478 "P2pGo");
11479
11480 /* Cancel any remain on channel for GO mode */
11481 if (NL80211_IFTYPE_P2P_GO == type) {
11482 wlan_hdd_cancel_existing_remain_on_channel
11483 (pAdapter);
11484 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011485
Arun Khandavallifae92942016-08-01 13:31:08 +053011486 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011487 /* De-init the adapter */
11488 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11489 memset(&pAdapter->sessionCtx, 0,
11490 sizeof(pAdapter->sessionCtx));
11491 pAdapter->device_mode =
11492 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011493 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11494 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011495
11496 /*
11497 * Fw will take care incase of concurrency
11498 */
11499
Krunal Sonib4326f22016-03-10 13:05:51 -080011500 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011501 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011502 /* To meet Android requirements create
11503 * a randomized MAC address of the
11504 * form 02:1A:11:Fx:xx:xx
11505 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011506 get_random_bytes(&ndev->dev_addr[3], 3);
11507 ndev->dev_addr[0] = 0x02;
11508 ndev->dev_addr[1] = 0x1A;
11509 ndev->dev_addr[2] = 0x11;
11510 ndev->dev_addr[3] |= 0xF0;
11511 memcpy(pAdapter->macAddressCurrent.
11512 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011513 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011514 pr_info("wlan: Generated HotSpot BSSID "
11515 MAC_ADDRESS_STR "\n",
11516 MAC_ADDR_ARRAY(ndev->dev_addr));
11517 }
11518
11519 hdd_set_ap_ops(pAdapter->dev);
11520
Arun Khandavallifae92942016-08-01 13:31:08 +053011521 if (hdd_start_adapter(pAdapter)) {
11522 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011523 return -EINVAL;
11524 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011525 /* Interface type changed update in wiphy structure */
11526 if (wdev) {
11527 wdev->iftype = type;
11528 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011529 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011530 return -EINVAL;
11531 }
11532 goto done;
11533 }
11534
11535 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011536 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011537 return -EOPNOTSUPP;
11538 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011539 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11540 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 switch (type) {
11542 case NL80211_IFTYPE_STATION:
11543 case NL80211_IFTYPE_P2P_CLIENT:
11544 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011545 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11546 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011547 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011548 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011549 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011550 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011551 pAdapter->device_mode);
11552 return -EINVAL;
11553 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011554 goto done;
11555
11556 case NL80211_IFTYPE_AP:
11557 case NL80211_IFTYPE_P2P_GO:
11558 wdev->iftype = type;
11559 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011560 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011561 goto done;
11562
11563 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011564 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011565 return -EOPNOTSUPP;
11566 }
11567 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011568 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011569 pAdapter->device_mode);
11570 return -EOPNOTSUPP;
11571 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011572done:
11573 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011574 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11575 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011576
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011577 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011578
11579 EXIT();
11580 return 0;
11581}
11582
Rajeev Kumar98edb772016-01-19 12:42:19 -080011583/**
11584 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11585 * @wiphy: Pointer to the wiphy structure
11586 * @ndev: Pointer to the net device
11587 * @type: Interface type
11588 * @flags: Flags for change interface
11589 * @params: Pointer to change interface parameters
11590 *
11591 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011592 */
11593static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11594 struct net_device *ndev,
11595 enum nl80211_iftype type,
11596 u32 *flags,
11597 struct vif_params *params)
11598{
11599 int ret;
11600
11601 cds_ssr_protect(__func__);
11602 ret =
11603 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11604 cds_ssr_unprotect(__func__);
11605
11606 return ret;
11607}
11608
Frank Liud4b2fa02017-03-29 11:46:48 +080011609#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011610static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11611 int index, uint8_t match)
11612{
11613 int i;
11614 for (i = 0; i < index; i++) {
11615 if (arr[i] == match)
11616 return true;
11617 }
11618 return false;
11619}
11620#endif
11621
11622/**
11623 * __wlan_hdd_change_station() - change station
11624 * @wiphy: Pointer to the wiphy structure
11625 * @dev: Pointer to the net device.
11626 * @mac: bssid
11627 * @params: Pointer to station parameters
11628 *
11629 * Return: 0 for success, error number on failure.
11630 */
11631#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11632static int __wlan_hdd_change_station(struct wiphy *wiphy,
11633 struct net_device *dev,
11634 const uint8_t *mac,
11635 struct station_parameters *params)
11636#else
11637static int __wlan_hdd_change_station(struct wiphy *wiphy,
11638 struct net_device *dev,
11639 uint8_t *mac,
11640 struct station_parameters *params)
11641#endif
11642{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011643 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011644 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11645 hdd_context_t *pHddCtx;
11646 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011647 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011648#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011649 tCsrStaParams StaParams = { 0 };
11650 uint8_t isBufSta = 0;
11651 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011652 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011653#endif
11654 int ret;
11655
11656 ENTER();
11657
Anurag Chouhan6d760662016-02-20 16:05:43 +053011658 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011659 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011660 return -EINVAL;
11661 }
11662
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011663 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664 TRACE_CODE_HDD_CHANGE_STATION,
11665 pAdapter->sessionId, params->listen_interval));
11666
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011667 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11668 hdd_err("invalid session id: %d", pAdapter->sessionId);
11669 return -EINVAL;
11670 }
11671
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011672 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11673 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011674 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011675 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011676
11677 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11678
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011679 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011680
Krunal Sonib4326f22016-03-10 13:05:51 -080011681 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11682 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011683 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11684 status =
11685 hdd_softap_change_sta_state(pAdapter,
11686 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011687 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011688
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011689 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011690 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691 return -EINVAL;
11692 }
11693 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011694 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11695 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011696 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011697#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11698 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11699 dev, mac, params);
11700#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011701
11702 if (cds_is_sub_20_mhz_enabled()) {
11703 hdd_err("TDLS not allowed with sub 20 MHz");
11704 return -EINVAL;
11705 }
11706
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011707 StaParams.capability = params->capability;
11708 StaParams.uapsd_queues = params->uapsd_queues;
11709 StaParams.max_sp = params->max_sp;
11710
11711 /* Convert (first channel , number of channels) tuple to
11712 * the total list of channels. This goes with the assumption
11713 * that if the first channel is < 14, then the next channels
11714 * are an incremental of 1 else an incremental of 4 till the number
11715 * of channels.
11716 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011717 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011718 if (0 != params->supported_channels_len) {
11719 int i = 0, j = 0, k = 0, no_of_channels = 0;
11720 int num_unique_channels;
11721 int next;
11722 for (i = 0;
11723 i < params->supported_channels_len
11724 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11725 int wifi_chan_index;
11726 if (!wlan_hdd_is_duplicate_channel
11727 (StaParams.supported_channels, j,
11728 params->supported_channels[i])) {
11729 StaParams.
11730 supported_channels[j] =
11731 params->
11732 supported_channels[i];
11733 } else {
11734 continue;
11735 }
11736 wifi_chan_index =
11737 ((StaParams.supported_channels[j] <=
11738 HDD_CHANNEL_14) ? 1 : 4);
11739 no_of_channels =
11740 params->supported_channels[i + 1];
11741
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011742 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 -080011743 StaParams.
11744 supported_channels[j],
11745 wifi_chan_index,
11746 no_of_channels);
11747 for (k = 1; k <= no_of_channels &&
11748 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11749 k++) {
11750 next =
11751 StaParams.
11752 supported_channels[j] +
11753 wifi_chan_index;
11754 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11755 StaParams.
11756 supported_channels[j
11757 +
11758 1]
11759 = next;
11760 } else {
11761 continue;
11762 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011763 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011764 j + 1,
11765 StaParams.
11766 supported_channels[j +
11767 1]);
11768 j += 1;
11769 }
11770 }
11771 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011772 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011773 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011774 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011775 StaParams.
11776 supported_channels[i]);
11777 }
11778 if (MAX_CHANNEL < num_unique_channels)
11779 num_unique_channels = MAX_CHANNEL;
11780 StaParams.supported_channels_len =
11781 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011782 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011783 StaParams.supported_channels_len);
11784 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011785 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011786 params->supported_oper_classes,
11787 params->supported_oper_classes_len);
11788 StaParams.supported_oper_classes_len =
11789 params->supported_oper_classes_len;
11790
11791 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011792 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011793 params->ext_capab,
11794 sizeof(StaParams.extn_capability));
11795
11796 if (NULL != params->ht_capa) {
11797 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011798 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011799 sizeof(tSirHTCap));
11800 }
11801
11802 StaParams.supported_rates_len =
11803 params->supported_rates_len;
11804
11805 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11806 * The supported_rates array , for all the structures propogating till Add Sta
11807 * to the firmware has to be modified , if the supplicant (ieee80211) is
11808 * modified to send more rates.
11809 */
11810
11811 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11812 */
11813 if (StaParams.supported_rates_len >
11814 SIR_MAC_MAX_SUPP_RATES)
11815 StaParams.supported_rates_len =
11816 SIR_MAC_MAX_SUPP_RATES;
11817
11818 if (0 != StaParams.supported_rates_len) {
11819 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011820 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011821 params->supported_rates,
11822 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011823 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011824 StaParams.supported_rates_len);
11825 for (i = 0; i < StaParams.supported_rates_len;
11826 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011827 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011828 StaParams.supported_rates[i]);
11829 }
11830
11831 if (NULL != params->vht_capa) {
11832 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011833 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 params->vht_capa,
11835 sizeof(tSirVHTCap));
11836 }
11837
11838 if (0 != params->ext_capab_len) {
11839 /*Define A Macro : TODO Sunil */
11840 if ((1 << 4) & StaParams.extn_capability[3]) {
11841 isBufSta = 1;
11842 }
11843 /* TDLS Channel Switching Support */
11844 if ((1 << 6) & StaParams.extn_capability[3]) {
11845 isOffChannelSupported = 1;
11846 }
11847 }
11848
Nitesh Shah99934ac2016-09-05 15:54:08 +053011849 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011850 (params->ht_capa || params->vht_capa ||
11851 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011852 is_qos_wmm_sta = true;
11853
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011854 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011855 " is_qos_wmm_sta= %d HTcapPresent = %d",
11856 __func__, is_qos_wmm_sta,
11857 StaParams.htcap_present);
11858
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011859 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011860 &StaParams,
11861 isBufSta,
11862 isOffChannelSupported,
11863 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011864 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011865 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011866 return -EINVAL;
11867 }
11868
11869 status =
11870 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11871 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011872 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011873 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011874 return -EINVAL;
11875 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011876#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011877 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011878 }
11879 EXIT();
11880 return ret;
11881}
11882
11883/**
11884 * wlan_hdd_change_station() - cfg80211 change station handler function
11885 * @wiphy: Pointer to the wiphy structure
11886 * @dev: Pointer to the net device.
11887 * @mac: bssid
11888 * @params: Pointer to station parameters
11889 *
11890 * This is the cfg80211 change station handler function which invokes
11891 * the internal function @__wlan_hdd_change_station with
11892 * SSR protection.
11893 *
11894 * Return: 0 for success, error number on failure.
11895 */
11896#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11897static int wlan_hdd_change_station(struct wiphy *wiphy,
11898 struct net_device *dev,
11899 const u8 *mac,
11900 struct station_parameters *params)
11901#else
11902static int wlan_hdd_change_station(struct wiphy *wiphy,
11903 struct net_device *dev,
11904 u8 *mac,
11905 struct station_parameters *params)
11906#endif
11907{
11908 int ret;
11909
11910 cds_ssr_protect(__func__);
11911 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11912 cds_ssr_unprotect(__func__);
11913
11914 return ret;
11915}
11916
11917/*
11918 * FUNCTION: __wlan_hdd_cfg80211_add_key
11919 * This function is used to initialize the key information
11920 */
11921static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11922 struct net_device *ndev,
11923 u8 key_index, bool pairwise,
11924 const u8 *mac_addr,
11925 struct key_params *params)
11926{
11927 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11928 tCsrRoamSetKey setKey;
11929 int status;
11930 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011931 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011932 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011933 hdd_context_t *pHddCtx;
11934 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11935
11936 ENTER();
11937
Anurag Chouhan6d760662016-02-20 16:05:43 +053011938 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011939 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011940 return -EINVAL;
11941 }
11942
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011943 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011944 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011945 return -EINVAL;
11946 }
11947
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011948 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011949 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11950 pAdapter->sessionId, params->key_len));
11951 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11952 status = wlan_hdd_validate_context(pHddCtx);
11953
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011954 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011955 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011956
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011957 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011958 hdd_device_mode_to_string(pAdapter->device_mode),
11959 pAdapter->device_mode);
11960
11961 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011962 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011963
11964 return -EINVAL;
11965 }
11966
11967 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011968 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011969
11970 return -EINVAL;
11971 }
11972
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011973 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011974
11975 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011976 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011977 setKey.keyId = key_index;
11978 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011979 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011980
11981 switch (params->cipher) {
11982 case WLAN_CIPHER_SUITE_WEP40:
11983 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11984 break;
11985
11986 case WLAN_CIPHER_SUITE_WEP104:
11987 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11988 break;
11989
11990 case WLAN_CIPHER_SUITE_TKIP:
11991 {
11992 u8 *pKey = &setKey.Key[0];
11993 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11994
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011995 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011996
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011997 /* Supplicant sends the 32bytes key in this order
11998 *
11999 * |--------------|----------|----------|
12000 * | Tk1 |TX-MIC | RX Mic |
12001 * |--------------|----------|----------|
12002 * <---16bytes---><--8bytes--><--8bytes-->
12003 *
12004 * Sme expects the 32 bytes key to be in the below order
12005 *
12006 * |--------------|----------|----------|
12007 * | Tk1 |RX-MIC | TX Mic |
12008 * |--------------|----------|----------|
12009 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012010 */
12011 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012012 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012013
12014 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012015 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012016
12017 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012018 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012019
12020 break;
12021 }
12022
12023 case WLAN_CIPHER_SUITE_CCMP:
12024 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
12025 break;
12026
12027#ifdef FEATURE_WLAN_WAPI
12028 case WLAN_CIPHER_SUITE_SMS4:
12029 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012030 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012031 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
12032 mac_addr, params->key,
12033 params->key_len);
12034 return 0;
12035 }
12036#endif
12037
12038#ifdef FEATURE_WLAN_ESE
12039 case WLAN_CIPHER_SUITE_KRK:
12040 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
12041 break;
12042#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12043 case WLAN_CIPHER_SUITE_BTK:
12044 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
12045 break;
12046#endif
12047#endif
12048
12049#ifdef WLAN_FEATURE_11W
12050 case WLAN_CIPHER_SUITE_AES_CMAC:
12051 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
12052 break;
12053#endif
12054
12055 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012056 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012057 return -EOPNOTSUPP;
12058 }
12059
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012060 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012061
12062 if (!pairwise) {
12063 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012064 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012065 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012066 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012067 } else {
12068 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012069 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012070 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012071 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012072 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012073 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012074 /* if a key is already installed, block all subsequent ones */
12075 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012076 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012077 return 0;
12078 }
12079
12080 setKey.keyDirection = eSIR_TX_RX;
12081 /*Set the group key */
12082 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12083 pAdapter->sessionId, &setKey, &roamId);
12084
12085 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012086 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012087 return -EINVAL;
12088 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012089 /* Save the keys here and call sme_roam_set_key for setting
12090 * the PTK after peer joins the IBSS network
12091 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012092 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012093 &setKey, sizeof(tCsrRoamSetKey));
12094
12095 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
12096 return status;
12097 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012098 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
12099 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
12101 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070012102 status = wlansap_set_key_sta(
12103 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012104 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012105 hdd_err("wlansap_set_key_sta failed status: %d",
12106 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012107 }
12108 }
12109
12110 /* Save the key in ap ctx for use on START_BASS and restart */
12111 if (pairwise ||
12112 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
12113 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012114 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012115 sizeof(tCsrRoamSetKey));
12116 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012117 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012118 sizeof(tCsrRoamSetKey));
12119
Krunal Sonib4326f22016-03-10 13:05:51 -080012120 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
12121 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012122 hdd_wext_state_t *pWextState =
12123 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12124 hdd_station_ctx_t *pHddStaCtx =
12125 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12126
12127 if (!pairwise) {
12128 /* set group key */
12129 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012130 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012131 __func__, __LINE__);
12132 hdd_perform_roam_set_key_complete(pAdapter);
12133 }
12134 }
12135
12136 pWextState->roamProfile.Keys.KeyLength[key_index] =
12137 (u8) params->key_len;
12138
12139 pWextState->roamProfile.Keys.defaultIndex = key_index;
12140
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012141 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012142 KeyMaterial[key_index][0], params->key,
12143 params->key_len);
12144
12145 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
12146
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012147 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012148 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12149 setKey.keyDirection);
12150
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012151 /* The supplicant may attempt to set the PTK once
12152 * pre-authentication is done. Save the key in the
12153 * UMAC and include it in the ADD BSS request
12154 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012155 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012156 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012157 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012158 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012159 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012160 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012161 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012162 return -EINVAL;
12163 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012164
12165 /* issue set key request to SME */
12166 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12167 pAdapter->sessionId, &setKey, &roamId);
12168
12169 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012170 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012171 pHddStaCtx->roam_info.roamingState =
12172 HDD_ROAM_STATE_NONE;
12173 return -EINVAL;
12174 }
12175
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012176 /* in case of IBSS as there was no information
12177 * available about WEP keys during IBSS join, group
12178 * key intialized with NULL key, so re-initialize
12179 * group key with correct value
12180 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012181 if ((eCSR_BSS_TYPE_START_IBSS ==
12182 pWextState->roamProfile.BSSType)
12183 &&
12184 !((IW_AUTH_KEY_MGMT_802_1X ==
12185 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
12186 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
12187 pHddStaCtx->conn_info.authType)
12188 )
12189 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
12190 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
12191 )
12192 ) {
12193 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012194 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012195
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012196 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012197 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12198 setKey.keyDirection);
12199
12200 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12201 pAdapter->sessionId, &setKey,
12202 &roamId);
12203
12204 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012205 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012206 pHddStaCtx->roam_info.roamingState =
12207 HDD_ROAM_STATE_NONE;
12208 return -EINVAL;
12209 }
12210 }
12211 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012212 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012213 return 0;
12214}
12215
12216static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12217 struct net_device *ndev,
12218 u8 key_index, bool pairwise,
12219 const u8 *mac_addr,
12220 struct key_params *params)
12221{
12222 int ret;
12223 cds_ssr_protect(__func__);
12224 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
12225 mac_addr, params);
12226 cds_ssr_unprotect(__func__);
12227
12228 return ret;
12229}
12230
12231/*
12232 * FUNCTION: __wlan_hdd_cfg80211_get_key
12233 * This function is used to get the key information
12234 */
12235static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12236 struct net_device *ndev,
12237 u8 key_index, bool pairwise,
12238 const u8 *mac_addr, void *cookie,
12239 void (*callback)(void *cookie,
12240 struct key_params *)
12241 )
12242{
12243 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12244 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12245 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
12246 struct key_params params;
12247
12248 ENTER();
12249
Anurag Chouhan6d760662016-02-20 16:05:43 +053012250 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012251 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012252 return -EINVAL;
12253 }
12254
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012255 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012256 hdd_device_mode_to_string(pAdapter->device_mode),
12257 pAdapter->device_mode);
12258
12259 memset(&params, 0, sizeof(params));
12260
12261 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012262 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012263 return -EINVAL;
12264 }
12265
12266 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12267 case eCSR_ENCRYPT_TYPE_NONE:
12268 params.cipher = IW_AUTH_CIPHER_NONE;
12269 break;
12270
12271 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12272 case eCSR_ENCRYPT_TYPE_WEP40:
12273 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12274 break;
12275
12276 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12277 case eCSR_ENCRYPT_TYPE_WEP104:
12278 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12279 break;
12280
12281 case eCSR_ENCRYPT_TYPE_TKIP:
12282 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12283 break;
12284
12285 case eCSR_ENCRYPT_TYPE_AES:
12286 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12287 break;
12288
12289 default:
12290 params.cipher = IW_AUTH_CIPHER_NONE;
12291 break;
12292 }
12293
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012294 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012295 TRACE_CODE_HDD_CFG80211_GET_KEY,
12296 pAdapter->sessionId, params.cipher));
12297
12298 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12299 params.seq_len = 0;
12300 params.seq = NULL;
12301 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12302 callback(cookie, &params);
12303
12304 EXIT();
12305 return 0;
12306}
12307
12308static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12309 struct net_device *ndev,
12310 u8 key_index, bool pairwise,
12311 const u8 *mac_addr, void *cookie,
12312 void (*callback)(void *cookie,
12313 struct key_params *)
12314 )
12315{
12316 int ret;
12317
12318 cds_ssr_protect(__func__);
12319 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12320 mac_addr, cookie, callback);
12321 cds_ssr_unprotect(__func__);
12322
12323 return ret;
12324}
12325
12326/**
12327 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12328 * @wiphy: wiphy interface context
12329 * @ndev: pointer to net device
12330 * @key_index: Key index used in 802.11 frames
12331 * @unicast: true if it is unicast key
12332 * @multicast: true if it is multicast key
12333 *
12334 * This function is required for cfg80211_ops API.
12335 * It is used to delete the key information
12336 * Underlying hardware implementation does not have API to delete the
12337 * encryption key. It is automatically deleted when the peer is
12338 * removed. Hence this function currently does nothing.
12339 * Future implementation may interprete delete key operation to
12340 * replacing the key with a random junk value, effectively making it
12341 * useless.
12342 *
12343 * Return: status code, always 0.
12344 */
12345
12346static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12347 struct net_device *ndev,
12348 u8 key_index,
12349 bool pairwise, const u8 *mac_addr)
12350{
12351 EXIT();
12352 return 0;
12353}
12354
12355/**
12356 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12357 * @wiphy: Pointer to wiphy structure.
12358 * @dev: Pointer to net_device structure.
12359 * @key_index: key index
12360 * @pairwise: pairwise
12361 * @mac_addr: mac address
12362 *
12363 * This is the cfg80211 delete key handler function which invokes
12364 * the internal function @__wlan_hdd_cfg80211_del_key with
12365 * SSR protection.
12366 *
12367 * Return: 0 for success, error number on failure.
12368 */
12369static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12370 struct net_device *dev,
12371 u8 key_index,
12372 bool pairwise, const u8 *mac_addr)
12373{
12374 int ret;
12375
12376 cds_ssr_protect(__func__);
12377 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12378 pairwise, mac_addr);
12379 cds_ssr_unprotect(__func__);
12380
12381 return ret;
12382}
12383
12384/*
12385 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12386 * This function is used to set the default tx key index
12387 */
12388static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12389 struct net_device *ndev,
12390 u8 key_index,
12391 bool unicast, bool multicast)
12392{
12393 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12394 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12395 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12396 hdd_context_t *pHddCtx;
12397 int status;
12398
12399 ENTER();
12400
Anurag Chouhan6d760662016-02-20 16:05:43 +053012401 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012402 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012403 return -EINVAL;
12404 }
12405
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012406 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012407 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012408 return -EINVAL;
12409 }
12410
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012411 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012412 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12413 pAdapter->sessionId, key_index));
12414
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012415 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012416 hdd_device_mode_to_string(pAdapter->device_mode),
12417 pAdapter->device_mode, key_index);
12418
12419 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012420 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012421 return -EINVAL;
12422 }
12423
12424 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12425 status = wlan_hdd_validate_context(pHddCtx);
12426
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012427 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012428 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012429
Krunal Sonib4326f22016-03-10 13:05:51 -080012430 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12431 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012432 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12433 pHddStaCtx->conn_info.ucEncryptionType) &&
12434 (eCSR_ENCRYPT_TYPE_AES !=
12435 pHddStaCtx->conn_info.ucEncryptionType)) {
12436 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012437 * then update the default key index
12438 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012439
12440 tCsrRoamSetKey setKey;
12441 uint32_t roamId = 0xFF;
12442 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12443
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012444 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012445
12446 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012447 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012448 setKey.keyId = key_index;
12449 setKey.keyLength = Keys->KeyLength[key_index];
12450
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012451 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012452 &Keys->KeyMaterial[key_index][0],
12453 Keys->KeyLength[key_index]);
12454
12455 setKey.keyDirection = eSIR_TX_RX;
12456
Anurag Chouhanc5548422016-02-24 18:33:27 +053012457 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458 &pHddStaCtx->conn_info.bssId);
12459
12460 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12461 pWextState->roamProfile.EncryptionType.
12462 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012463 /* In the case of dynamic wep
12464 * supplicant hardcodes DWEP type to
12465 * eCSR_ENCRYPT_TYPE_WEP104 even
12466 * though ap is configured for WEP-40
12467 * encryption. In this canse the key
12468 * length is 5 but the encryption type
12469 * is 104 hence checking the key
12470 * lenght(5) and encryption type(104)
12471 * and switching encryption type to 40
12472 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012473 pWextState->roamProfile.EncryptionType.
12474 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12475 pWextState->roamProfile.mcEncryptionType.
12476 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12477 }
12478
12479 setKey.encType =
12480 pWextState->roamProfile.EncryptionType.
12481 encryptionType[0];
12482
12483 /* Issue set key request */
12484 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12485 pAdapter->sessionId, &setKey,
12486 &roamId);
12487
12488 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012489 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012490 status);
12491 return -EINVAL;
12492 }
12493 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012494 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012495 /* In SoftAp mode setting key direction for default mode */
12496 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12497 pWextState->roamProfile.EncryptionType.encryptionType[0])
12498 && (eCSR_ENCRYPT_TYPE_AES !=
12499 pWextState->roamProfile.EncryptionType.
12500 encryptionType[0])) {
12501 /* Saving key direction for default key index to TX default */
12502 hdd_ap_ctx_t *pAPCtx =
12503 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12504 pAPCtx->wepKey[key_index].keyDirection =
12505 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012506 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012507 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012508 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012509 }
12510 }
12511
12512 EXIT();
12513 return status;
12514}
12515
12516static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12517 struct net_device *ndev,
12518 u8 key_index,
12519 bool unicast, bool multicast)
12520{
12521 int ret;
12522 cds_ssr_protect(__func__);
12523 ret =
12524 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12525 multicast);
12526 cds_ssr_unprotect(__func__);
12527
12528 return ret;
12529}
12530
Abhishek Singhc9941602016-08-09 16:06:22 +053012531/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012532 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12533 * interface that BSS might have been lost.
12534 * @pAdapter: adaptor
12535 * @bssid: bssid which might have been lost
12536 *
12537 * Return: bss which is unlinked from kernel cache
12538 */
12539struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12540 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012541{
12542 struct net_device *dev = pAdapter->dev;
12543 struct wireless_dev *wdev = dev->ieee80211_ptr;
12544 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012545 struct cfg80211_bss *bss = NULL;
12546
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012547 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012548 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012549 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012550 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012551 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012552 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012553 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012554 cfg80211_unlink_bss(wiphy, bss);
12555 }
12556 return bss;
12557}
12558
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012559#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12560 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12561static struct cfg80211_bss *
12562wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12563 struct ieee80211_channel *chan,
12564 struct ieee80211_mgmt *mgmt,
12565 size_t frame_len,
12566 int rssi, gfp_t gfp,
12567 uint64_t boottime_ns)
12568{
12569 struct cfg80211_bss *bss_status = NULL;
12570 struct cfg80211_inform_bss data = {0};
12571
12572 data.chan = chan;
12573 data.boottime_ns = boottime_ns;
12574 data.signal = rssi;
12575 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12576 frame_len, gfp);
12577 return bss_status;
12578}
12579#else
12580static struct cfg80211_bss *
12581wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12582 struct ieee80211_channel *chan,
12583 struct ieee80211_mgmt *mgmt,
12584 size_t frame_len,
12585 int rssi, gfp_t gfp,
12586 uint64_t boottime_ns)
12587{
12588 struct cfg80211_bss *bss_status = NULL;
12589
12590 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12591 rssi, gfp);
12592 return bss_status;
12593}
12594#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012595
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012596/**
12597 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12598 * @pAdapter: Pointer to adapter
12599 * @bss_desc: Pointer to bss descriptor
12600 *
12601 * This function is used to inform the BSS details to nl80211 interface.
12602 *
12603 * Return: struct cfg80211_bss pointer
12604 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012605struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12606 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607{
12608 /*
12609 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12610 * already exists in bss data base of cfg80211 for that particular BSS
12611 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12612 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12613 * As of now there is no possibility to get the mgmt(probe response)
12614 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12615 * and passing to cfg80211_inform_bss_frame.
12616 */
12617 struct net_device *dev = pAdapter->dev;
12618 struct wireless_dev *wdev = dev->ieee80211_ptr;
12619 struct wiphy *wiphy = wdev->wiphy;
12620 int chan_no = bss_desc->channelId;
12621#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12622 qcom_ie_age *qie_age = NULL;
12623 int ie_length =
12624 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12625#else
12626 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12627#endif
12628 const char *ie =
12629 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12630 unsigned int freq;
12631 struct ieee80211_channel *chan;
12632 struct ieee80211_mgmt *mgmt = NULL;
12633 struct cfg80211_bss *bss_status = NULL;
12634 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12635 int rssi = 0;
12636 hdd_context_t *pHddCtx;
12637 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012638 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012639 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012640
12641 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12642 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012643 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012644 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012645
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012646 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012647 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012648 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012649 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012650 return NULL;
12651 }
12652
12653 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12654
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012655 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012656 * Instead it wants a monotonic increasing value
12657 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012658 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012659 mgmt->u.probe_resp.timestamp =
12660 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012661
12662 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12663 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12664
12665#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12666 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12667 /* Assuming this is the last IE, copy at the end */
12668 ie_length -= sizeof(qcom_ie_age);
12669 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12670 qie_age->element_id = QCOM_VENDOR_IE_ID;
12671 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12672 qie_age->oui_1 = QCOM_OUI1;
12673 qie_age->oui_2 = QCOM_OUI2;
12674 qie_age->oui_3 = QCOM_OUI3;
12675 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012676 /*
12677 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12678 * all bss related timestamp is in units of ms. Due to this when scan
12679 * results are sent to lowi the scan age is high.To address this,
12680 * send age in units of 1/10 ms.
12681 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012682 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012683 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012684 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012685 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12686 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012687 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12688 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012689#endif
12690
12691 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12692 if (bss_desc->fProbeRsp) {
12693 mgmt->frame_control |=
12694 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12695 } else {
12696 mgmt->frame_control |=
12697 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12698 }
12699
12700 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012701 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012702 freq =
12703 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012704 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012705 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012706 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012707 freq =
12708 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012709 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012711 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012712 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012713 return NULL;
12714 }
12715
12716 chan = __ieee80211_get_channel(wiphy, freq);
12717 /* When the band is changed on the fly using the GUI, three things are done
12718 * 1. scan abort
12719 * 2. flush scan results from cache
12720 * 3. update the band with the new band user specified (refer to the
12721 * hdd_set_band_helper function) as part of the scan abort, message will be
12722 * queued to PE and we proceed with flushing and changinh the band.
12723 * PE will stop the scanning further and report back the results what ever
12724 * it had till now by calling the call back function.
12725 * if the time between update band and scandone call back is sufficient
12726 * enough the band change reflects in SME, SME validates the channels
12727 * and discards the channels correponding to previous band and calls back
12728 * with zero bss results. but if the time between band update and scan done
12729 * callback is very small then band change will not reflect in SME and SME
12730 * reports to HDD all the channels correponding to previous band.this is due
12731 * to race condition.but those channels are invalid to the new band and so
12732 * this function __ieee80211_get_channel will return NULL.Each time we
12733 * report scan result with this pointer null warning kernel trace is printed.
12734 * if the scan results contain large number of APs continuosly kernel
12735 * warning trace is printed and it will lead to apps watch dog bark.
12736 * So drop the bss and continue to next bss.
12737 */
12738 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012739 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12740 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012741 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012742 return NULL;
12743 }
12744
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012745 /* Based on .ini configuration, raw rssi can be reported for bss.
12746 * Raw rssi is typically used for estimating power.
12747 */
12748
12749 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12750 bss_desc->rssi;
12751
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012752 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012753 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012754
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012755 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012756 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012757 (int)(rssi / 100),
12758 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012759
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012760 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12761 frame_len, rssi,
12762 GFP_KERNEL,
12763 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012764 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012765 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012766 return bss_status;
12767}
12768
12769/**
12770 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12771 * @pAdapter: Pointer to adapter
12772 * @pRoamInfo: Pointer to roam info
12773 *
12774 * This function is used to update the BSS data base of CFG8011
12775 *
12776 * Return: struct cfg80211_bss pointer
12777 */
12778struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12779 tCsrRoamInfo *pRoamInfo)
12780{
12781 tCsrRoamConnectedProfile roamProfile;
12782 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12783 struct cfg80211_bss *bss = NULL;
12784
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012785 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12786 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12787
12788 if (NULL != roamProfile.pBssDesc) {
12789 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12790 roamProfile.pBssDesc);
12791
12792 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012793 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012794
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012795 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012796 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012797 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012798 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012799 return bss;
12800}
12801/**
12802 * wlan_hdd_cfg80211_update_bss() - update bss
12803 * @wiphy: Pointer to wiphy
12804 * @pAdapter: Pointer to adapter
12805 * @scan_time: scan request timestamp
12806 *
12807 * Return: zero if success, non-zero otherwise
12808 */
12809int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12810 hdd_adapter_t *pAdapter,
12811 uint32_t scan_time)
12812{
12813 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12814 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012815 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012816 tScanResultHandle pResult;
12817 struct cfg80211_bss *bss_status = NULL;
12818 hdd_context_t *pHddCtx;
12819 int ret;
12820
12821 ENTER();
12822
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012823 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12824 hdd_err("invalid session id: %d", pAdapter->sessionId);
12825 return -EINVAL;
12826 }
12827
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012828 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012829 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12830 NO_SESSION, pAdapter->sessionId));
12831
12832 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12833 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012834 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012835 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012836
12837 /* start getting scan results and populate cgf80211 BSS database */
12838 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12839
12840 /* no scan results */
12841 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012842 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012843 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012844 }
12845
12846 pScanResult = sme_scan_result_get_first(hHal, pResult);
12847
12848 while (pScanResult) {
12849 /*
12850 * - cfg80211_inform_bss() is not updating ie field of bss
12851 * entry if entry already exists in bss data base of cfg80211
12852 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12853 * to update thebss entry instead of cfg80211_inform_bss,
12854 * But this call expects mgmt packet as input. As of now
12855 * there is no possibility to get the mgmt(probe response)
12856 * frame from PE, converting bss_desc to
12857 * ieee80211_mgmt(probe response) and passing to c
12858 * fg80211_inform_bss_frame.
12859 * - Update BSS only if beacon timestamp is later than
12860 * scan request timestamp.
12861 */
12862 if ((scan_time == 0) ||
12863 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012864 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012865 bss_status =
12866 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12867 &pScanResult->BssDescriptor);
12868
12869 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012870 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012871 } else {
12872 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012873 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012874 bss_status);
12875 }
12876 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012877 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012878 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12879 }
12880 pScanResult = sme_scan_result_get_next(hHal, pResult);
12881 }
12882
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012883 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012884 /*
12885 * For SAP mode, scan is invoked by hostapd during SAP start
12886 * if hostapd is restarted, we need to flush previous scan
12887 * result so that it will reflect environment change
12888 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012889 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012890#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12891 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12892#endif
12893 )
12894 sme_scan_flush_result(hHal);
12895
12896 EXIT();
12897 return 0;
12898}
12899
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012900/**
12901 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12902 * @pAdapter: Pointer to adapter
12903 * @pRoamInfo: Pointer to roam info
12904 * @index: Index
12905 * @preauth: Preauth flag
12906 *
12907 * This function is used to notify the supplicant of a new PMKSA candidate.
12908 *
12909 * Return: 0 for success, non-zero for failure
12910 */
12911int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12912 tCsrRoamInfo *pRoamInfo,
12913 int index, bool preauth)
12914{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012915 struct net_device *dev = pAdapter->dev;
12916 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12917
12918 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012919 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012920
12921 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012922 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012923 return -EINVAL;
12924 }
12925
12926 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012927 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012928 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12929 cfg80211_pmksa_candidate_notify(dev, index,
12930 pRoamInfo->bssid.bytes,
12931 preauth, GFP_KERNEL);
12932 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012933 return 0;
12934}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012935
12936#ifdef FEATURE_WLAN_LFR_METRICS
12937/**
12938 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12939 * @pAdapter: Pointer to adapter
12940 * @pRoamInfo: Pointer to roam info
12941 *
12942 * 802.11r/LFR metrics reporting function to report preauth initiation
12943 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012944 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012945 */
12946#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012947QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012948 tCsrRoamInfo *pRoamInfo)
12949{
12950 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12951 union iwreq_data wrqu;
12952
12953 ENTER();
12954
12955 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012956 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012957 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012958 }
12959
12960 /* create the event */
12961 memset(&wrqu, 0, sizeof(wrqu));
12962 memset(metrics_notification, 0, sizeof(metrics_notification));
12963
12964 wrqu.data.pointer = metrics_notification;
12965 wrqu.data.length = scnprintf(metrics_notification,
12966 sizeof(metrics_notification),
12967 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053012968 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012969
12970 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12971 metrics_notification);
12972
12973 EXIT();
12974
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012975 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012976}
12977
12978/**
12979 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12980 * @pAdapter: Pointer to adapter
12981 * @pRoamInfo: Pointer to roam info
12982 * @preauth_status: Preauth status
12983 *
12984 * 802.11r/LFR metrics reporting function to report handover initiation
12985 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012986 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012987 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012988QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012989wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12990 tCsrRoamInfo *pRoamInfo,
12991 bool preauth_status)
12992{
12993 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12994 union iwreq_data wrqu;
12995
12996 ENTER();
12997
12998 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012999 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013000 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013001 }
13002
13003 /* create the event */
13004 memset(&wrqu, 0, sizeof(wrqu));
13005 memset(metrics_notification, 0, sizeof(metrics_notification));
13006
13007 scnprintf(metrics_notification, sizeof(metrics_notification),
13008 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013009 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013010
13011 if (1 == preauth_status)
13012 strlcat(metrics_notification, " true",
13013 sizeof(metrics_notification));
13014 else
13015 strlcat(metrics_notification, " false",
13016 sizeof(metrics_notification));
13017
13018 wrqu.data.pointer = metrics_notification;
13019 wrqu.data.length = strlen(metrics_notification);
13020
13021 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13022 metrics_notification);
13023
13024 EXIT();
13025
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013026 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013027}
13028
13029/**
13030 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13031 * @pAdapter: Pointer to adapter
13032 * @pRoamInfo: Pointer to roam info
13033 *
13034 * 802.11r/LFR metrics reporting function to report handover initiation
13035 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013036 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013037 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013038QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013039 tCsrRoamInfo *pRoamInfo)
13040{
13041 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13042 union iwreq_data wrqu;
13043
13044 ENTER();
13045
13046 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013047 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013048 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013049 }
13050
13051 /* create the event */
13052 memset(&wrqu, 0, sizeof(wrqu));
13053 memset(metrics_notification, 0, sizeof(metrics_notification));
13054
13055 wrqu.data.pointer = metrics_notification;
13056 wrqu.data.length = scnprintf(metrics_notification,
13057 sizeof(metrics_notification),
13058 "QCOM: LFR_PREAUTH_HANDOVER "
13059 MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013060 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013061
13062 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13063 metrics_notification);
13064
13065 EXIT();
13066
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013067 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013068}
13069#endif
13070
13071/**
13072 * hdd_select_cbmode() - select channel bonding mode
13073 * @pAdapter: Pointer to adapter
13074 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013075 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076 *
13077 * Return: none
13078 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013079void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080013080 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013081{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013082 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013083 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013084 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013085 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013086
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013087 /*
13088 * CDS api expects secondary channel for calculating
13089 * the channel params
13090 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013091 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013092 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013093 if (operationChannel >= 1 && operationChannel <= 5)
13094 sec_ch = operationChannel + 4;
13095 else if (operationChannel >= 6 && operationChannel <= 13)
13096 sec_ch = operationChannel - 4;
13097 }
13098
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013099 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013100 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
13101 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013102
13103 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070013104 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013105 uint8_t iniDot11Mode =
13106 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
13107
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013108 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013109 switch (iniDot11Mode) {
13110 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080013111 case eHDD_DOT11_MODE_11ax:
13112 case eHDD_DOT11_MODE_11ax_ONLY:
13113 if (sme_is_feature_supported_by_fw(DOT11AX))
13114 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
13115 else if (sme_is_feature_supported_by_fw(DOT11AC))
13116 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13117 else
13118 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13119 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013120 case eHDD_DOT11_MODE_11ac:
13121 case eHDD_DOT11_MODE_11ac_ONLY:
13122 if (sme_is_feature_supported_by_fw(DOT11AC))
13123 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13124 else
13125 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13126 break;
13127 case eHDD_DOT11_MODE_11n:
13128 case eHDD_DOT11_MODE_11n_ONLY:
13129 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13130 break;
13131 default:
13132 hdd_dot11_mode = iniDot11Mode;
13133 break;
13134 }
13135 ch_info->channel_width = ch_params->ch_width;
13136 ch_info->phy_mode =
13137 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013138 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013139 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013140 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013141 ch_info->channel_width, ch_info->phy_mode,
13142 ch_info->channel);
13143 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013144}
13145
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013146/**
13147 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
13148 * @adapter: STA adapter
13149 * @roam_profile: STA roam profile
13150 *
13151 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
13152 *
13153 * Return: false if sta-sap conc is not allowed, else return true
13154 */
13155static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
13156 tCsrRoamProfile *roam_profile)
13157{
13158 hdd_context_t *hdd_ctx;
13159 hdd_adapter_t *ap_adapter;
13160 hdd_ap_ctx_t *hdd_ap_ctx;
13161 hdd_hostapd_state_t *hostapd_state;
13162 uint8_t channel = 0;
13163 QDF_STATUS status;
13164
13165 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13166 if (!hdd_ctx) {
13167 hdd_err("HDD context is NULL");
13168 return true;
13169 }
13170
13171 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
13172 /* probably no sap running, no handling required */
13173 if (ap_adapter == NULL)
13174 return true;
13175
13176 /*
13177 * sap is not in started state, so it is fine to go ahead with sta.
13178 * if sap is currently doing CAC then don't allow sta to go further.
13179 */
13180 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
13181 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
13182 return true;
13183
13184 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
13185 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
13186 return false;
13187 }
13188
13189 /*
13190 * log and return error, if we allow STA to go through, we don't
13191 * know what is going to happen better stop sta connection
13192 */
13193 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
13194 if (NULL == hdd_ap_ctx) {
13195 hdd_err("AP context not found");
13196 return false;
13197 }
13198
13199 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013200 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
13201 hdd_ap_ctx->operatingChannel)) {
13202 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013203 return true;
13204 }
13205 /*
13206 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053013207 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013208 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013209 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013210 roam_profile, &channel);
13211
Nitesh Shah59774522016-09-16 15:14:21 +053013212 /*
13213 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
13214 * channels for roaming case.
13215 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013216 if (WLAN_REG_IS_24GHZ_CH(channel)) {
13217 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053013218 return true;
13219 }
13220
13221 /*
13222 * If channel is 0 or DFS then better to call pcl and find out the
13223 * best channel. If channel is non-dfs 5 GHz then better move SAP
13224 * to STA's channel to make scc, so we have room for 3port MCC
13225 * scenario.
13226 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013227 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013228 channel = policy_mgr_get_nondfs_preferred_channel(
13229 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013230
13231 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
13232 qdf_event_reset(&hostapd_state->qdf_event);
13233 status = wlansap_set_channel_change_with_csa(
13234 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
13235 hdd_ap_ctx->sapConfig.ch_width_orig);
13236
13237 if (QDF_STATUS_SUCCESS != status) {
13238 hdd_err("Set channel with CSA IE failed, can't allow STA");
13239 return false;
13240 }
13241
13242 /*
13243 * wait here for SAP to finish the channel switch. When channel
13244 * switch happens, SAP sends few beacons with CSA_IE. After
13245 * successfully Transmission of those beacons, it will move its
13246 * state from started to disconnected and move to new channel.
13247 * once it moves to new channel, sap again moves its state
13248 * machine from disconnected to started and set this event.
13249 * wait for 10 secs to finish this.
13250 */
13251 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
13252 if (!QDF_IS_STATUS_SUCCESS(status)) {
13253 hdd_err("wait for qdf_event failed, STA not allowed!!");
13254 return false;
13255 }
13256
13257 return true;
13258}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013259
Abhishek Singhcfb44482017-03-10 12:42:37 +053013260#ifdef WLAN_FEATURE_11W
13261/**
13262 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13263 * @roam_profile: pointer to roam profile
13264 *
13265 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13266 * or pmf=2 is an explicit configuration in the supplicant
13267 * configuration, drop the connection request.
13268 *
13269 * Return: 0 if check result is valid, otherwise return error code
13270 */
13271static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13272{
13273 if (roam_profile->MFPEnabled &&
13274 !(roam_profile->MFPRequired ||
13275 roam_profile->MFPCapable)) {
13276 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13277 roam_profile->MFPEnabled,
13278 roam_profile->MFPRequired,
13279 roam_profile->MFPCapable);
13280 return -EINVAL;
13281 }
13282 return 0;
13283}
13284#else
13285static inline
13286int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13287{
13288 return 0;
13289}
13290#endif
13291
Krunal Soni31949422016-07-29 17:17:53 -070013292/**
13293 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013294 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013295 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013296 * @ssid_len: Length of ssid
13297 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013298 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013299 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013300 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013301 *
13302 * This function is used to start the association process
13303 *
13304 * Return: 0 for success, non-zero for failure
13305 */
Krunal Soni31949422016-07-29 17:17:53 -070013306static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013307 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013308 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013309 u8 operatingChannel,
13310 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013311{
13312 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013313 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013314 hdd_wext_state_t *pWextState;
13315 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013316 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013317 uint32_t roamId;
13318 tCsrRoamProfile *pRoamProfile;
13319 eCsrAuthType RSNAuthType;
13320 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013321 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013322
13323 ENTER();
13324
13325 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13326 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013327 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013328
13329 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013330 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013331 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013332
13333 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013334 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013335 status = -EINVAL;
13336 goto ret_status;
13337 }
13338
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013339 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013340 hdd_err("Connection refused: conn in progress");
13341 status = -EINVAL;
13342 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013343 }
13344
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013345 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013346 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13347
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013348 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013349 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13350 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013351
13352 if (pRoamProfile) {
13353 hdd_station_ctx_t *pHddStaCtx;
13354 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13355
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013356 /* Restart the opportunistic timer
13357 *
13358 * If hw_mode_change_in_progress is true, then wait
13359 * till firmware sends the callback for hw_mode change.
13360 *
13361 * Else set connect_in_progress as true and proceed.
13362 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013363 policy_mgr_restart_opportunistic_timer(
13364 pHddCtx->hdd_psoc, false);
13365 if (policy_mgr_is_hw_mode_change_in_progress(
13366 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013367 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013368 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013369 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013370 hdd_err("qdf wait for event failed!!");
13371 status = -EINVAL;
13372 goto ret_status;
13373 }
13374 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013375 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013376
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013377 if (HDD_WMM_USER_MODE_NO_QOS ==
13378 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13379 /*QoS not enabled in cfg file */
13380 pRoamProfile->uapsd_mask = 0;
13381 } else {
13382 /*QoS enabled, update uapsd mask from cfg file */
13383 pRoamProfile->uapsd_mask =
13384 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13385 }
13386
13387 pRoamProfile->SSIDs.numOfSSIDs = 1;
13388 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013389 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013390 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013391 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013392 ssid, ssid_len);
13393
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013394 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013395 /* cleanup bssid hint */
13396 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13397 QDF_MAC_ADDR_SIZE);
13398 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13399 QDF_MAC_ADDR_SIZE);
13400
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013401 if (bssid) {
13402 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013403 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013404 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013405 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013406 /*
13407 * Save BSSID in seperate variable as
13408 * pRoamProfile's BSSID is getting zeroed out in the
13409 * association process. In case of join failure
13410 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013411 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013412 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013413 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013414 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013415 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013416 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13417 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013418 /*
13419 * Save BSSID in a separate variable as
13420 * pRoamProfile's BSSID is getting zeroed out in the
13421 * association process. In case of join failure
13422 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013423 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013424 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013425 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013426 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013427 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013428 }
13429
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013430 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013431 pRoamProfile->SSIDs.SSIDList->SSID.length,
13432 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13433 operatingChannel);
13434
13435 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13436 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013437 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013438 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13439 }
13440#ifdef FEATURE_WLAN_WAPI
13441 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013442 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013443 switch (pAdapter->wapi_info.wapiAuthMode) {
13444 case WAPI_AUTH_MODE_PSK:
13445 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013446 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013447 pAdapter->wapi_info.wapiAuthMode);
13448 pRoamProfile->AuthType.authType[0] =
13449 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13450 break;
13451 }
13452 case WAPI_AUTH_MODE_CERT:
13453 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013454 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455 pAdapter->wapi_info.wapiAuthMode);
13456 pRoamProfile->AuthType.authType[0] =
13457 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13458 break;
13459 }
13460 } /* End of switch */
13461 if (pAdapter->wapi_info.wapiAuthMode ==
13462 WAPI_AUTH_MODE_PSK
13463 || pAdapter->wapi_info.wapiAuthMode ==
13464 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013465 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013466 pRoamProfile->AuthType.numEntries = 1;
13467 pRoamProfile->EncryptionType.numEntries = 1;
13468 pRoamProfile->EncryptionType.encryptionType[0] =
13469 eCSR_ENCRYPT_TYPE_WPI;
13470 pRoamProfile->mcEncryptionType.numEntries = 1;
13471 pRoamProfile->mcEncryptionType.
13472 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13473 }
13474 }
Krunal Soni31949422016-07-29 17:17:53 -070013475#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013476 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013477 pRoamProfile->csrPersona = pAdapter->device_mode;
13478
13479 if (operatingChannel) {
13480 pRoamProfile->ChannelInfo.ChannelList =
13481 &operatingChannel;
13482 pRoamProfile->ChannelInfo.numOfChannels = 1;
13483 } else {
13484 pRoamProfile->ChannelInfo.ChannelList = NULL;
13485 pRoamProfile->ChannelInfo.numOfChannels = 0;
13486 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013487 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013488 && operatingChannel) {
13489 /*
13490 * Need to post the IBSS power save parameters
13491 * to WMA. WMA will configure this parameters
13492 * to firmware if power save is enabled by the
13493 * firmware.
13494 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013495 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013496
Abhishek Singh471652b2017-04-14 12:28:32 +053013497 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013498 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013499 status = -EINVAL;
13500 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013501 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013502 pRoamProfile->ch_params.ch_width =
13503 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013504 /*
13505 * In IBSS mode while operating in 2.4 GHz,
13506 * the device supports only 20 MHz.
13507 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013508 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013509 pRoamProfile->ch_params.ch_width =
13510 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013511 hdd_select_cbmode(pAdapter, operatingChannel,
13512 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513 }
13514
Abhishek Singhcfb44482017-03-10 12:42:37 +053013515 if (wlan_hdd_cfg80211_check_pmf_valid(
13516 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013517 status = -EINVAL;
13518 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013519 }
13520
Krunal Soni31949422016-07-29 17:17:53 -070013521 /*
13522 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013523 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013524 * enhancements, the supplicant is not issuing the scan command
13525 * now. So the unicast frames which are sent from the host are
13526 * not having the additional IEs. If it is P2P CLIENT and there
13527 * is no additional IE present in roamProfile, then use the
13528 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013529 */
13530
Krunal Sonib4326f22016-03-10 13:05:51 -080013531 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013532 (!pRoamProfile->pAddIEScan)) {
13533 pRoamProfile->pAddIEScan =
13534 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13535 pRoamProfile->nAddIEScanLength =
13536 pAdapter->scan_info.scanAddIE.length;
13537 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013538
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013539 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13540 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013541 pRoamProfile))) {
13542 hdd_err("sap-sta conc will fail, can't allow sta");
13543 hdd_conn_set_connection_state(pAdapter,
13544 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013545 status = -ENOMEM;
13546 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013547 }
13548
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013549 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013550 if (!sme_config) {
13551 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013552 hdd_conn_set_connection_state(pAdapter,
13553 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013554 status = -ENOMEM;
13555 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013556 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013557 sme_get_config_param(pHddCtx->hHal, sme_config);
13558 /* These values are not sessionized. So, any change in these SME
13559 * configs on an older or parallel interface will affect the
13560 * cb mode. So, restoring the default INI params before starting
13561 * interfaces such as sta, cli etc.,
13562 */
13563 sme_config->csrConfig.channelBondingMode5GHz =
13564 pHddCtx->config->nChannelBondingMode5GHz;
13565 sme_config->csrConfig.channelBondingMode24GHz =
13566 pHddCtx->config->nChannelBondingMode24GHz;
13567 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013568 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013569 /*
13570 * Change conn_state to connecting before sme_roam_connect(),
13571 * because sme_roam_connect() has a direct path to call
13572 * hdd_sme_roam_callback(), which will change the conn_state
13573 * If direct path, conn_state will be accordingly changed to
13574 * NotConnected or Associated by either
13575 * hdd_association_completion_handler() or
13576 * hdd_dis_connect_handler() in sme_RoamCallback()if
13577 * sme_RomConnect is to be queued,
13578 * Connecting state will remain until it is completed.
13579 *
13580 * If connection state is not changed, connection state will
13581 * remain in eConnectionState_NotConnected state.
13582 * In hdd_association_completion_handler, "hddDisconInProgress"
13583 * is set to true if conn state is
13584 * eConnectionState_NotConnected.
13585 * If "hddDisconInProgress" is set to true then cfg80211 layer
13586 * is not informed of connect result indication which
13587 * is an issue.
13588 */
13589 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013590 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013591 hdd_conn_set_connection_state(pAdapter,
13592 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013593
Komal Seelama89be8d2016-09-29 11:09:26 +053013594 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13595 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013596 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013597 pAdapter->sessionId, pRoamProfile,
13598 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013599 if (QDF_IS_STATUS_ERROR(qdf_status))
13600 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013601
Rajeev Kumard31e1542017-01-13 14:37:42 -080013602 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013603 (QDF_STA_MODE == pAdapter->device_mode ||
13604 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013605 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013606 "qdf_status %d. -> NotConnected",
13607 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013608 /* change back to NotAssociated */
13609 hdd_conn_set_connection_state(pAdapter,
13610 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013611 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13612 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013613 }
13614
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013615 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013616 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013617
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013618 pRoamProfile->ChannelInfo.ChannelList = NULL;
13619 pRoamProfile->ChannelInfo.numOfChannels = 0;
13620
Nitesh Shah044fd672016-10-13 18:53:25 +053013621 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013622 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13623 && !policy_mgr_is_hw_dbs_2x2_capable(
13624 pHddCtx->hdd_psoc)) {
13625 policy_mgr_get_channel_from_scan_result(
13626 pHddCtx->hdd_psoc,
13627 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013628 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013629 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013630 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13631 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013632 }
13633
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013634 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013635 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013636 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013637 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013638 goto ret_status;
13639
13640conn_failure:
13641 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013642 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013643
13644ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013645 EXIT();
13646 return status;
13647}
13648
13649/**
13650 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13651 * @pAdapter: Pointer to adapter
13652 * @auth_type: Auth type
13653 *
13654 * This function is used to set the authentication type (OPEN/SHARED).
13655 *
13656 * Return: 0 for success, non-zero for failure
13657 */
13658static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13659 enum nl80211_auth_type auth_type)
13660{
13661 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13662 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13663
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013664 /*set authentication type */
13665 switch (auth_type) {
13666 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013667 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013668 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13669 break;
13670
13671 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013672 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013673 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013674 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13675 break;
13676
13677 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013678 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013679 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13680 break;
13681#ifdef FEATURE_WLAN_ESE
13682 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013683 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013684 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13685 break;
13686#endif
13687
13688 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013689 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013690 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13691 return -EINVAL;
13692 }
13693
13694 pWextState->roamProfile.AuthType.authType[0] =
13695 pHddStaCtx->conn_info.authType;
13696 return 0;
13697}
13698
13699/**
13700 * wlan_hdd_set_akm_suite() - set key management type
13701 * @pAdapter: Pointer to adapter
13702 * @key_mgmt: Key management type
13703 *
13704 * This function is used to set the key mgmt type(PSK/8021x).
13705 *
13706 * Return: 0 for success, non-zero for failure
13707 */
13708static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13709{
13710 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13711
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013712#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013713#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013714#endif
13715#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013716#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013717#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013718 /*set key mgmt type */
13719 switch (key_mgmt) {
13720 case WLAN_AKM_SUITE_PSK:
13721 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013722 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013723 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013724 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13725 break;
13726
13727 case WLAN_AKM_SUITE_8021X_SHA256:
13728 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013729 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013730 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013731 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13732 break;
13733#ifdef FEATURE_WLAN_ESE
13734#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13735#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13736 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013737 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013738 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13739 break;
13740#endif
13741#ifndef WLAN_AKM_SUITE_OSEN
13742#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13743#endif
13744 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013745 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013746 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13747 break;
13748
13749 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013750 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013751 return -EINVAL;
13752
13753 }
13754 return 0;
13755}
13756
13757/**
13758 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13759 * @pAdapter: Pointer to adapter
13760 * @cipher: Cipher type
13761 * @ucast: Unicast flag
13762 *
13763 * This function is used to set the encryption type
13764 * (NONE/WEP40/WEP104/TKIP/CCMP).
13765 *
13766 * Return: 0 for success, non-zero for failure
13767 */
13768static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13769 u32 cipher, bool ucast)
13770{
13771 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13772 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13773 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13774
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013775 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013776 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013777 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13778 } else {
13779
13780 /*set encryption method */
13781 switch (cipher) {
13782 case IW_AUTH_CIPHER_NONE:
13783 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13784 break;
13785
13786 case WLAN_CIPHER_SUITE_WEP40:
13787 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13788 break;
13789
13790 case WLAN_CIPHER_SUITE_WEP104:
13791 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13792 break;
13793
13794 case WLAN_CIPHER_SUITE_TKIP:
13795 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13796 break;
13797
13798 case WLAN_CIPHER_SUITE_CCMP:
13799 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13800 break;
13801#ifdef FEATURE_WLAN_WAPI
13802 case WLAN_CIPHER_SUITE_SMS4:
13803 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13804 break;
13805#endif
13806
13807#ifdef FEATURE_WLAN_ESE
13808 case WLAN_CIPHER_SUITE_KRK:
13809 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13810 break;
13811#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13812 case WLAN_CIPHER_SUITE_BTK:
13813 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13814 break;
13815#endif
13816#endif
13817 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013818 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013819 return -EOPNOTSUPP;
13820 }
13821 }
13822
13823 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013824 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013825 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13826 pWextState->roamProfile.EncryptionType.numEntries = 1;
13827 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13828 encryptionType;
13829 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013830 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13832 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13833 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13834 encryptionType;
13835 }
13836
13837 return 0;
13838}
13839
13840/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013841 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13842 * @wext_state: Pointer to wext state
13843 * @gen_ie: Pointer to IE data
13844 * @len: length of IE data
13845 *
13846 * Return: 0 for success, non-zero for failure
13847 */
13848static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13849 const uint8_t *gen_ie, uint16_t len)
13850{
13851 uint16_t cur_add_ie_len =
13852 wext_state->assocAddIE.length;
13853
13854 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13855 (wext_state->assocAddIE.length + len)) {
13856 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13857 QDF_ASSERT(0);
13858 return -ENOMEM;
13859 }
13860 memcpy(wext_state->assocAddIE.addIEdata +
13861 cur_add_ie_len, gen_ie, len);
13862 wext_state->assocAddIE.length += len;
13863
13864 wext_state->roamProfile.pAddIEAssoc =
13865 wext_state->assocAddIE.addIEdata;
13866 wext_state->roamProfile.nAddIEAssocLength =
13867 wext_state->assocAddIE.length;
13868 return 0;
13869}
13870
13871/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013872 * wlan_hdd_cfg80211_set_ie() - set IEs
13873 * @pAdapter: Pointer to adapter
13874 * @ie: Pointer ot ie
13875 * @ie: IE length
13876 *
13877 * Return: 0 for success, non-zero for failure
13878 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013879static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880 size_t ie_len)
13881{
13882 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13883 const uint8_t *genie = ie;
13884 uint16_t remLen = ie_len;
13885#ifdef FEATURE_WLAN_WAPI
13886 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13887 u16 *tmp;
13888 uint16_t akmsuiteCount;
13889 int *akmlist;
13890#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013891 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013892
13893 /* clear previous assocAddIE */
13894 pWextState->assocAddIE.length = 0;
13895 pWextState->roamProfile.bWPSAssociation = false;
13896 pWextState->roamProfile.bOSENAssociation = false;
13897
13898 while (remLen >= 2) {
13899 uint16_t eLen = 0;
13900 uint8_t elementId;
13901 elementId = *genie++;
13902 eLen = *genie++;
13903 remLen -= 2;
13904
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013905 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013906
13907 switch (elementId) {
13908 case DOT11F_EID_WPA:
13909 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 -070013910 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013911 return -EINVAL;
13912 } else if (0 ==
13913 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13914 uint16_t curAddIELen =
13915 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013916 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013917
13918 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13919 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013920 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013921 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013922 return -ENOMEM;
13923 }
13924 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13925 memcpy(pWextState->assocAddIE.addIEdata +
13926 curAddIELen, genie - 2, eLen + 2);
13927 pWextState->assocAddIE.length += eLen + 2;
13928
13929 pWextState->roamProfile.bWPSAssociation = true;
13930 pWextState->roamProfile.pAddIEAssoc =
13931 pWextState->assocAddIE.addIEdata;
13932 pWextState->roamProfile.nAddIEAssocLength =
13933 pWextState->assocAddIE.length;
13934 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013935 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013936 memset(pWextState->WPARSNIE, 0,
13937 MAX_WPA_RSN_IE_LEN);
13938 memcpy(pWextState->WPARSNIE, genie - 2,
13939 (eLen + 2));
13940 pWextState->roamProfile.pWPAReqIE =
13941 pWextState->WPARSNIE;
13942 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13943 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13944 P2P_OUI_TYPE_SIZE))) {
13945 uint16_t curAddIELen =
13946 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013947 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013948
13949 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13950 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013951 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013952 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 return -ENOMEM;
13954 }
13955 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13956 memcpy(pWextState->assocAddIE.addIEdata +
13957 curAddIELen, genie - 2, eLen + 2);
13958 pWextState->assocAddIE.length += eLen + 2;
13959
13960 pWextState->roamProfile.pAddIEAssoc =
13961 pWextState->assocAddIE.addIEdata;
13962 pWextState->roamProfile.nAddIEAssocLength =
13963 pWextState->assocAddIE.length;
13964 }
13965#ifdef WLAN_FEATURE_WFD
13966 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13967 WFD_OUI_TYPE_SIZE)) &&
13968 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013969 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013970 pAdapter->device_mode)) {
13971 uint16_t curAddIELen =
13972 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013973 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013974
13975 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13976 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013977 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013978 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979 return -ENOMEM;
13980 }
13981 /* WFD IE is saved to Additional IE ; it should
13982 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013983 * WFD IE
13984 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013985 memcpy(pWextState->assocAddIE.addIEdata +
13986 curAddIELen, genie - 2, eLen + 2);
13987 pWextState->assocAddIE.length += eLen + 2;
13988
13989 pWextState->roamProfile.pAddIEAssoc =
13990 pWextState->assocAddIE.addIEdata;
13991 pWextState->roamProfile.nAddIEAssocLength =
13992 pWextState->assocAddIE.length;
13993 }
13994#endif
13995 /* Appending HS 2.0 Indication Element in Assiciation Request */
13996 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13997 HS20_OUI_TYPE_SIZE))) {
13998 uint16_t curAddIELen =
13999 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014000 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014001
14002 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14003 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014004 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014005 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014006 return -ENOMEM;
14007 }
14008 memcpy(pWextState->assocAddIE.addIEdata +
14009 curAddIELen, genie - 2, eLen + 2);
14010 pWextState->assocAddIE.length += eLen + 2;
14011
14012 pWextState->roamProfile.pAddIEAssoc =
14013 pWextState->assocAddIE.addIEdata;
14014 pWextState->roamProfile.nAddIEAssocLength =
14015 pWextState->assocAddIE.length;
14016 }
14017 /* Appending OSEN Information Element in Assiciation Request */
14018 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
14019 OSEN_OUI_TYPE_SIZE))) {
14020 uint16_t curAddIELen =
14021 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014022 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014023
14024 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14025 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014026 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014027 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014028 return -ENOMEM;
14029 }
14030 memcpy(pWextState->assocAddIE.addIEdata +
14031 curAddIELen, genie - 2, eLen + 2);
14032 pWextState->assocAddIE.length += eLen + 2;
14033
14034 pWextState->roamProfile.bOSENAssociation = true;
14035 pWextState->roamProfile.pAddIEAssoc =
14036 pWextState->assocAddIE.addIEdata;
14037 pWextState->roamProfile.nAddIEAssocLength =
14038 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014039 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
14040 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014041 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014042 status = wlan_hdd_add_assoc_ie(pWextState,
14043 genie - 2, eLen + 2);
14044 if (status)
14045 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 } else {
14047 uint16_t add_ie_len =
14048 pWextState->assocAddIE.length;
14049
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014050 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014051
14052 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14053 (pWextState->assocAddIE.length + eLen)) {
14054 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014055 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014056 return -ENOMEM;
14057 }
14058
14059 memcpy(pWextState->assocAddIE.addIEdata +
14060 add_ie_len, genie - 2, eLen + 2);
14061 pWextState->assocAddIE.length += eLen + 2;
14062
14063 pWextState->roamProfile.pAddIEAssoc =
14064 pWextState->assocAddIE.addIEdata;
14065 pWextState->roamProfile.nAddIEAssocLength =
14066 pWextState->assocAddIE.length;
14067 }
14068 break;
14069 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014070 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014071 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
14072 memcpy(pWextState->WPARSNIE, genie - 2,
14073 (eLen + 2));
14074 pWextState->roamProfile.pRSNReqIE =
14075 pWextState->WPARSNIE;
14076 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
14077 break;
14078 /*
14079 * Appending Extended Capabilities with Interworking bit set
14080 * in Assoc Req.
14081 *
14082 * In assoc req this EXT Cap will only be taken into account if
14083 * interworkingService bit is set to 1. Currently
14084 * driver is only interested in interworkingService capability
14085 * from supplicant. If in future any other EXT Cap info is
14086 * required from supplicat, it needs to be handled while
14087 * sending Assoc Req in LIM.
14088 */
14089 case DOT11F_EID_EXTCAP:
14090 {
14091 uint16_t curAddIELen =
14092 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014093 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014094
14095 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14096 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014097 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014098 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014099 return -ENOMEM;
14100 }
14101 memcpy(pWextState->assocAddIE.addIEdata +
14102 curAddIELen, genie - 2, eLen + 2);
14103 pWextState->assocAddIE.length += eLen + 2;
14104
14105 pWextState->roamProfile.pAddIEAssoc =
14106 pWextState->assocAddIE.addIEdata;
14107 pWextState->roamProfile.nAddIEAssocLength =
14108 pWextState->assocAddIE.length;
14109 break;
14110 }
14111#ifdef FEATURE_WLAN_WAPI
14112 case WLAN_EID_WAPI:
14113 /* Setting WAPI Mode to ON=1 */
14114 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014115 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014116 tmp = (u16 *) ie;
14117 tmp = tmp + 2; /* Skip element Id and Len, Version */
14118 akmsuiteCount = WPA_GET_LE16(tmp);
14119 tmp = tmp + 1;
14120 akmlist = (int *)(tmp);
14121 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
14122 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
14123 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014124 hdd_err("Invalid akmSuite count: %u",
14125 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014126 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014127 return -EINVAL;
14128 }
14129
14130 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014131 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014132 pAdapter->wapi_info.wapiAuthMode =
14133 WAPI_AUTH_MODE_PSK;
14134 }
14135 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014136 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014137 pAdapter->wapi_info.wapiAuthMode =
14138 WAPI_AUTH_MODE_CERT;
14139 }
14140 break;
14141#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014142 case DOT11F_EID_SUPPOPERATINGCLASSES:
14143 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014144 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014145 status = wlan_hdd_add_assoc_ie(pWextState,
14146 genie - 2, eLen + 2);
14147 if (status)
14148 return status;
14149 break;
14150 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014151 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014152 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014153 /* when Unknown IE is received we break
14154 * and continue to the next IE in the buffer
14155 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014156 break;
14157 }
14158 genie += eLen;
14159 remLen -= eLen;
14160 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161 return 0;
14162}
14163
14164/**
14165 * hdd_is_wpaie_present() - check for WPA ie
14166 * @ie: Pointer to ie
14167 * @ie_len: Ie length
14168 *
14169 * Parse the received IE to find the WPA IE
14170 *
14171 * Return: true if wpa ie is found else false
14172 */
14173static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
14174{
14175 uint8_t eLen = 0;
14176 uint16_t remLen = ie_len;
14177 uint8_t elementId = 0;
14178
14179 while (remLen >= 2) {
14180 elementId = *ie++;
14181 eLen = *ie++;
14182 remLen -= 2;
14183 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014184 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014185 return false;
14186 }
14187 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
14188 /* OUI - 0x00 0X50 0XF2
14189 * WPA Information Element - 0x01
14190 * WPA version - 0x01
14191 */
14192 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
14193 return true;
14194 }
14195 ie += eLen;
14196 remLen -= eLen;
14197 }
14198 return false;
14199}
14200
14201/**
14202 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
14203 * @pAdapter: Pointer to adapter
14204 * @req: Pointer to security parameters
14205 *
14206 * Return: 0 for success, non-zero for failure
14207 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014208static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
14209 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014210{
14211 int status = 0;
14212 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14213 ENTER();
14214
14215 /*set wpa version */
14216 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
14217
14218 if (req->crypto.wpa_versions) {
14219 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
14220 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
14221 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
14222 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14223 }
14224 }
14225
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014226 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014227
14228 /*set authentication type */
14229 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
14230
14231 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014232 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014233 return status;
14234 }
14235
14236 /*set key mgmt type */
14237 if (req->crypto.n_akm_suites) {
14238 status =
14239 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
14240 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014241 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014242 return status;
14243 }
14244 }
14245
14246 /*set pairwise cipher type */
14247 if (req->crypto.n_ciphers_pairwise) {
14248 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
14249 req->crypto.
14250 ciphers_pairwise[0],
14251 true);
14252 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014253 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014254 return status;
14255 }
14256 } else {
14257 /*Reset previous cipher suite to none */
14258 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14259 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014260 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014261 return status;
14262 }
14263 }
14264
14265 /*set group cipher type */
14266 status =
14267 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14268 false);
14269
14270 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014271 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014272 return status;
14273 }
14274#ifdef WLAN_FEATURE_11W
14275 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14276#endif
14277
14278 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14279 if (req->ie_len) {
14280 status =
14281 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14282 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014283 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014284 return status;
14285 }
14286 }
14287
14288 /*incase of WEP set default key information */
14289 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014290 u8 key_len = req->key_len;
14291 u8 key_idx = req->key_idx;
14292
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014293 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14294 || (WLAN_CIPHER_SUITE_WEP104 ==
14295 req->crypto.ciphers_pairwise[0])
14296 ) {
14297 if (IW_AUTH_KEY_MGMT_802_1X
14298 ==
14299 (pWextState->
14300 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014301 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014302 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014303 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014304
Jeff Johnson68755312017-02-10 11:46:55 -080014305 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14306 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014307 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014308 key_idx, key_len);
14309 qdf_mem_copy(&pWextState->roamProfile.
14310 Keys.
14311 KeyMaterial[key_idx][0],
14312 req->key, key_len);
14313 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014314 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014315 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014316 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014317 }
14318 }
14319 }
14320
14321 return status;
14322}
14323
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014324int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014325{
14326 unsigned long rc;
14327 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014328 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014329 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014330
14331 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014332 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14333 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014334 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014335 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14336 }
14337 /*
14338 * If firmware has already started roaming process, driver
14339 * needs to defer the processing of this disconnect request.
14340 *
14341 */
14342 if (hdd_is_roaming_in_progress(pAdapter)) {
14343 /*
14344 * Defer the disconnect action until firmware roaming
14345 * result is received. If STA is in connected state after
14346 * that, send the disconnect command to CSR, otherwise
14347 * CSR would have already sent disconnect event to upper
14348 * layer.
14349 */
14350
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014351 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014352 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14353 pAdapter->cfg80211_disconnect_reason =
14354 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14355 return 0;
14356 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014357
Jeff Johnson9edf9572016-10-03 15:24:49 -070014358 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014359 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14360 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14361 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014362 hdd_conn_set_connection_state(pAdapter,
14363 eConnectionState_Disconnecting);
14364 /* Issue disconnect to CSR */
14365 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014366
14367 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14368 pAdapter->sessionId,
14369 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14370 /*
14371 * Wait here instead of returning directly, this will block the
14372 * next connect command and allow processing of the scan for
14373 * ssid and the previous connect command in CSR. Else we might
14374 * hit some race conditions leading to SME and HDD out of sync.
14375 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014376 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014377 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014378 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014379 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014380 (int)status);
14381 pHddStaCtx->staDebugState = status;
14382 result = -EINVAL;
14383 goto disconnected;
14384 }
14385
14386 rc = wait_for_completion_timeout(
14387 &pAdapter->disconnect_comp_var,
14388 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014389 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014390 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014391 pAdapter->sessionId, pHddStaCtx->staDebugState);
14392 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014393 }
14394 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014395 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014396 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014397 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014398 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014399 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014400 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014401 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014402 }
14403 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014404disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014405 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14406 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014407}
14408
14409/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014410 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14411 * @adapter: Pointer to the HDD adapter
14412 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014413 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014414 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014415 * This function will start reassociation if prev_bssid is set and bssid/
14416 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014417 *
Naveen Rawat07332902016-07-27 09:13:17 -070014418 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014419 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014420#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14421 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014422static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14423 struct cfg80211_connect_params *req,
14424 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014425{
Naveen Rawat07332902016-07-27 09:13:17 -070014426 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014427 const uint8_t *bssid = NULL;
14428 uint16_t channel = 0;
Arif Hussain43354e62017-05-24 11:24:25 -070014429 hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014430
14431 if (req->bssid)
14432 bssid = req->bssid;
14433 else if (req->bssid_hint)
14434 bssid = req->bssid_hint;
14435
14436 if (req->channel)
14437 channel = req->channel->hw_value;
14438 else if (req->channel_hint)
14439 channel = req->channel_hint->hw_value;
14440
14441 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014442 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014443 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014444 channel, MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070014445 /*
14446 * Save BSSID in a separate variable as
14447 * pRoamProfile's BSSID is getting zeroed out in the
14448 * association process. In case of join failure
14449 * we should send valid BSSID to supplicant
14450 */
14451 qdf_mem_copy(wext_state->req_bssId.bytes, bssid,
14452 QDF_MAC_ADDR_SIZE);
14453
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014454 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014455 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014456 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014457 }
Naveen Rawat07332902016-07-27 09:13:17 -070014458 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014459}
14460#else
Naveen Rawat07332902016-07-27 09:13:17 -070014461static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14462 struct cfg80211_connect_params *req,
14463 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014464{
Naveen Rawat07332902016-07-27 09:13:17 -070014465 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014466}
14467#endif
14468
14469/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014470 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14471 * @wiphy: Pointer to wiphy
14472 * @dev: Pointer to network device
14473 * @req: Pointer to cfg80211 connect request
14474 *
14475 * This function is used to start the association process
14476 *
14477 * Return: 0 for success, non-zero for failure
14478 */
14479static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14480 struct net_device *ndev,
14481 struct cfg80211_connect_params *req)
14482{
14483 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014484 u16 channel;
14485#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14486 const u8 *bssid_hint = req->bssid_hint;
14487#else
14488 const u8 *bssid_hint = NULL;
14489#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014490 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14491 hdd_context_t *pHddCtx;
14492
14493 ENTER();
14494
Anurag Chouhan6d760662016-02-20 16:05:43 +053014495 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014496 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014497 return -EINVAL;
14498 }
14499
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014500 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14501 hdd_err("invalid session id: %d", pAdapter->sessionId);
14502 return -EINVAL;
14503 }
14504
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014505 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014506 TRACE_CODE_HDD_CFG80211_CONNECT,
14507 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014508 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014509 hdd_device_mode_to_string(pAdapter->device_mode),
14510 pAdapter->device_mode);
14511
Krunal Sonib4326f22016-03-10 13:05:51 -080014512 if (pAdapter->device_mode != QDF_STA_MODE &&
14513 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014514 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014515 hdd_device_mode_to_string(pAdapter->device_mode),
14516 pAdapter->device_mode);
14517 return -EINVAL;
14518 }
14519
14520 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14521 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014522 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523 return -EINVAL;
14524 }
14525
14526 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014527 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014528 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014529
Naveen Rawat07332902016-07-27 09:13:17 -070014530 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014531 return status;
14532
Agrawal Ashishf156e942016-08-04 14:54:47 +053014533 /* Try disconnecting if already in connected state */
14534 status = wlan_hdd_try_disconnect(pAdapter);
14535 if (0 > status) {
14536 hdd_err("Failed to disconnect the existing connection");
14537 return -EALREADY;
14538 }
14539
14540 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014541 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014542 bool ok;
14543
14544 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14545 pHddCtx->hdd_psoc,
14546 req->channel->hw_value,
14547 &ok)) {
14548 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14549 req->channel->hw_value);
14550 return -EINVAL;
14551 }
14552 /**
14553 * Send connection timedout, so that Android framework does not
14554 * blacklist us.
14555 */
14556 if (!ok) {
14557 struct ieee80211_channel *chan =
14558 __ieee80211_get_channel(wiphy,
14559 wlan_chan_to_freq(req->channel->hw_value));
14560 struct cfg80211_bss *bss;
14561
14562 hdd_warn("Channel:%d not OK for DNBS",
14563 req->channel->hw_value);
14564 if (chan) {
14565 bss = hdd_cfg80211_get_bss(wiphy,
14566 chan,
14567 req->bssid, req->ssid,
14568 req->ssid_len);
14569 if (bss) {
14570 cfg80211_assoc_timeout(ndev, bss);
14571 return -ETIMEDOUT;
14572 }
14573 }
14574 return -EINVAL;
14575 }
14576
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014577 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14578 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014579 pAdapter->device_mode),
14580 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014581 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014582 return -ECONNREFUSED;
14583 }
14584 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014585 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14586 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014587 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014588 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014589 return -ECONNREFUSED;
14590 }
14591 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014592
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014593 /*initialise security parameters */
14594 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14595
14596 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014597 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014598 return status;
14599 }
14600
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014601 if (req->channel)
14602 channel = req->channel->hw_value;
14603 else
14604 channel = 0;
14605 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14606 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014607 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014608 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014609 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014610 return status;
14611 }
14612 EXIT();
14613 return status;
14614}
14615
14616/**
14617 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14618 * @wiphy: Pointer to wiphy
14619 * @dev: Pointer to network device
14620 * @req: Pointer to cfg80211 connect request
14621 *
14622 * Return: 0 for success, non-zero for failure
14623 */
14624static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14625 struct net_device *ndev,
14626 struct cfg80211_connect_params *req)
14627{
14628 int ret;
14629 cds_ssr_protect(__func__);
14630 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14631 cds_ssr_unprotect(__func__);
14632
14633 return ret;
14634}
14635
14636/**
14637 * wlan_hdd_disconnect() - hdd disconnect api
14638 * @pAdapter: Pointer to adapter
14639 * @reason: Disconnect reason code
14640 *
14641 * This function is used to issue a disconnect request to SME
14642 *
14643 * Return: 0 for success, non-zero for failure
14644 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014645static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014646{
14647 int status, result = 0;
14648 unsigned long rc;
14649 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14650 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014651 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014652 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014653
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014654 ENTER();
14655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014656 status = wlan_hdd_validate_context(pHddCtx);
14657
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014658 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014659 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014660 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014661 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014662 status = sme_stop_roaming(hal, pAdapter->sessionId,
14663 eCsrHddIssued);
14664 }
14665 /*
14666 * If firmware has already started roaming process, driver
14667 * needs to defer the processing of this disconnect request.
14668 */
14669 if (hdd_is_roaming_in_progress(pAdapter)) {
14670 /*
14671 * Defer the disconnect action until firmware roaming
14672 * result is received. If STA is in connected state after
14673 * that, send the disconnect command to CSR, otherwise
14674 * CSR would have already sent disconnect event to upper
14675 * layer.
14676 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014677 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014678 pAdapter->defer_disconnect =
14679 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14680 pAdapter->cfg80211_disconnect_reason = reason;
14681 return 0;
14682 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014683
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014684 prev_conn_state = pHddStaCtx->conn_info.connState;
14685
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014686 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014687 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014688 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014689 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014690 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014691 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14692 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14693
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014694 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014695
14696 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14697 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014698 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14699 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014700 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014701 result = 0;
14702 goto disconnected;
14703 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14704 /*
14705 * Wait here instead of returning directly, this will block the
14706 * next connect command and allow processing of the scan for
14707 * ssid and the previous connect command in CSR. Else we might
14708 * hit some race conditions leading to SME and HDD out of sync.
14709 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014710 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014711 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014712 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014713 pHddStaCtx->staDebugState = status;
14714 result = -EINVAL;
14715 goto disconnected;
14716 }
14717 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14718 msecs_to_jiffies
14719 (WLAN_WAIT_TIME_DISCONNECT));
14720
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014721 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014722 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014723 result = -ETIMEDOUT;
14724 }
14725disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014726 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14727#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14728 /* Sending disconnect event to userspace for kernel version < 3.11
14729 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14730 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014731 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014732 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14733 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014734#endif
14735
14736 return result;
14737}
14738
14739/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014740 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14741 * @reason: ieee80211 reason code.
14742 *
14743 * This utility function helps log string conversion of reason code.
14744 *
14745 * Return: string conversion of reason code, if match found;
14746 * "Unknown" otherwise.
14747 */
14748static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14749{
14750 switch (reason) {
14751 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14752 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14753 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14754 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14755 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14756 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14757 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14758 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14759 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14760 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14761 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14762 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14763 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14764 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14765 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14766 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14767 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14768 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14769 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14770 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14771 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14772 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14773 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14774 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14775 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14776 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14777 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14778 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14779 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14780 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14781 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14782 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14783 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14784 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14785 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14786 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14787 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14788 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14789 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14790 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14791 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14792 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14793 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14794 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14795 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14796 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14797 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14798 default:
14799 return "Unknown";
14800 }
14801}
14802
14803/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14805 * @wiphy: Pointer to wiphy
14806 * @dev: Pointer to network device
14807 * @reason: Disconnect reason code
14808 *
14809 * This function is used to issue a disconnect request to SME
14810 *
14811 * Return: 0 for success, non-zero for failure
14812 */
14813static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14814 struct net_device *dev, u16 reason)
14815{
14816 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14817 int status;
14818 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14819 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14820#ifdef FEATURE_WLAN_TDLS
14821 uint8_t staIdx;
14822#endif
14823
14824 ENTER();
14825
Anurag Chouhan6d760662016-02-20 16:05:43 +053014826 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014827 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014828 return -EINVAL;
14829 }
14830
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014831 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014832 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014833 return -EINVAL;
14834 }
14835
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014836 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014837 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14838 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014839 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014840 hdd_device_mode_to_string(pAdapter->device_mode),
14841 pAdapter->device_mode, reason);
14842
14843 status = wlan_hdd_validate_context(pHddCtx);
14844
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014845 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014846 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014847
14848 /* Issue disconnect request to SME, if station is in connected state */
14849 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14850 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14851 eCsrRoamDisconnectReason reasonCode =
14852 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14853 hdd_scaninfo_t *pScanInfo;
14854
14855 switch (reason) {
14856 case WLAN_REASON_MIC_FAILURE:
14857 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14858 break;
14859
14860 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14861 case WLAN_REASON_DISASSOC_AP_BUSY:
14862 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14863 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14864 break;
14865
14866 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14867 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14868 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14869 break;
14870
14871 case WLAN_REASON_DEAUTH_LEAVING:
14872 reasonCode =
14873 pHddCtx->config->
14874 gEnableDeauthToDisassocMap ?
14875 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14876 eCSR_DISCONNECT_REASON_DEAUTH;
14877 break;
14878 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14879 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14880 break;
14881 default:
14882 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14883 break;
14884 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014885 pScanInfo = &pAdapter->scan_info;
14886 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014887 hdd_debug("Disconnect is in progress, Aborting Scan");
Abhishek Singh69ccb512017-04-25 11:58:16 +053014888 wlan_abort_scan(pHddCtx->hdd_pdev, INVAL_PDEV_ID,
14889 pAdapter->sessionId, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014890 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014891 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014892#ifdef FEATURE_WLAN_TDLS
14893 /* First clean up the tdls peers if any */
14894 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14895 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14896 pAdapter->sessionId)
14897 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14898 uint8_t *mac;
14899 mac =
14900 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014901 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014902 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014903 pHddCtx->tdlsConnInfo[staIdx].staId,
14904 pAdapter->sessionId,
14905 MAC_ADDR_ARRAY(mac));
14906 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14907 (pAdapter),
14908 pAdapter->sessionId, mac);
14909 }
14910 }
Kabilan Kannanaad2f032017-05-08 13:25:37 -070014911 hdd_notify_sta_disconnect(pAdapter->sessionId,
14912 true, pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014913#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014914 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14915 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014916 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14917 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014918 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014919 return -EINVAL;
14920 }
14921 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014922 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014923 pHddStaCtx->conn_info.connState);
14924 }
14925
14926 return status;
14927}
14928
14929/**
14930 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14931 * @wiphy: Pointer to wiphy
14932 * @dev: Pointer to network device
14933 * @reason: Disconnect reason code
14934 *
14935 * Return: 0 for success, non-zero for failure
14936 */
14937static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14938 struct net_device *dev, u16 reason)
14939{
14940 int ret;
14941 cds_ssr_protect(__func__);
14942 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14943 cds_ssr_unprotect(__func__);
14944
14945 return ret;
14946}
14947
14948/**
14949 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14950 * @pAdapter: Pointer to adapter
14951 * @param: Pointer to IBSS parameters
14952 *
14953 * This function is used to initialize the security settings in IBSS mode
14954 *
14955 * Return: 0 for success, non-zero for failure
14956 */
14957static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14958 struct cfg80211_ibss_params
14959 *params)
14960{
14961 int status = 0;
14962 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14963 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14964 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14965
14966 ENTER();
14967
14968 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014969 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014970 pHddStaCtx->ibss_enc_key_installed = 0;
14971
14972 if (params->ie_len && (NULL != params->ie)) {
14973 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14974 params->ie_len, WLAN_EID_RSN)) {
14975 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14976 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14977 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14978 tDot11fIEWPA dot11WPAIE;
14979 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14980 u8 *ie;
14981
14982 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14983 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14984 params->ie_len,
14985 DOT11F_EID_WPA);
14986 if (NULL != ie) {
14987 pWextState->wpaVersion =
14988 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014989 /* Unpack the WPA IE
14990 * Skip past the EID byte and length byte
14991 * and four byte WiFi OUI
14992 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014993 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014994 &ie[2 + 4], ie[1] - 4,
14995 &dot11WPAIE, false);
14996 /*
14997 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014998 * encType for unicast cipher for
14999 * wpa-none is none
15000 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015001 encryptionType =
15002 hdd_translate_wpa_to_csr_encryption_type
15003 (dot11WPAIE.multicast_cipher);
15004 }
15005 }
15006
15007 status =
15008 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
15009 params->ie_len);
15010
15011 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015012 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015013 return status;
15014 }
15015 }
15016
15017 pWextState->roamProfile.AuthType.authType[0] =
15018 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
15019
15020 if (params->privacy) {
15021 /* Security enabled IBSS, At this time there is no information
15022 * available about the security paramters, so initialise the
15023 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
15024 * The correct security parameters will be updated later in
15025 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
15026 * set inorder enable privacy bit in beacons
15027 */
15028
15029 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
15030 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015031 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015032 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
15033 pWextState->roamProfile.EncryptionType.numEntries = 1;
15034 pWextState->roamProfile.EncryptionType.encryptionType[0] =
15035 encryptionType;
15036 return status;
15037}
15038
15039/**
15040 * __wlan_hdd_cfg80211_join_ibss() - join ibss
15041 * @wiphy: Pointer to wiphy
15042 * @dev: Pointer to network device
15043 * @param: Pointer to IBSS join parameters
15044 *
15045 * This function is used to create/join an IBSS network
15046 *
15047 * Return: 0 for success, non-zero for failure
15048 */
15049static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15050 struct net_device *dev,
15051 struct cfg80211_ibss_params *params)
15052{
15053 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15054 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15055 tCsrRoamProfile *pRoamProfile;
15056 int status;
15057 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15058 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053015059 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015060 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015061
15062 ENTER();
15063
Anurag Chouhan6d760662016-02-20 16:05:43 +053015064 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015065 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015066 return -EINVAL;
15067 }
15068
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015069 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015070 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015071 return -EINVAL;
15072 }
15073
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015074 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015075 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
15076 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015077 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015078 hdd_device_mode_to_string(pAdapter->device_mode),
15079 pAdapter->device_mode);
15080
15081 status = wlan_hdd_validate_context(pHddCtx);
15082
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015083 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015084 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015085
15086 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053015087 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015088 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
15089 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
15090 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15091 int indx;
15092
15093 /* Get channel number */
15094 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015095 params->
15096 chandef.
15097 chan->
15098 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015099
15100 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
15101 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015102 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015103 return -EOPNOTSUPP;
15104 }
15105
15106 for (indx = 0; indx < numChans; indx++) {
15107 if (channelNum == validChan[indx]) {
15108 break;
15109 }
15110 }
15111 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015112 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015113 return -EINVAL;
15114 }
15115 }
15116
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015117 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
15118 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015119 hdd_err("This concurrency combination is not allowed");
15120 return -ECONNREFUSED;
15121 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015122
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015123 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015124 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015125 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015126
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015127 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
15128 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070015129 SIR_UPDATE_REASON_JOIN_IBSS);
15130 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015131 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070015132 return -EINVAL;
15133 }
15134
15135 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015136 status = policy_mgr_wait_for_connection_update(
15137 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015138 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015139 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015140 return -EINVAL;
15141 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015142 }
15143
15144 /*Try disconnecting if already in connected state */
15145 status = wlan_hdd_try_disconnect(pAdapter);
15146 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015147 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015148 return -EALREADY;
15149 }
15150
15151 pRoamProfile = &pWextState->roamProfile;
15152
15153 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015154 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015155 return -EINVAL;
15156 }
15157
15158 /* enable selected protection checks in IBSS mode */
15159 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
15160
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015161 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015162 WNI_CFG_IBSS_ATIM_WIN_SIZE,
15163 pHddCtx->config->
15164 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015165 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015166 }
15167
15168 /* BSSID is provided by upper layers hence no need to AUTO generate */
15169 if (NULL != params->bssid) {
15170 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015171 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015172 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015173 return -EIO;
15174 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015175 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015176 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
15177 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015178 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015179 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015180 return -EIO;
15181 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053015182 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015183 }
15184 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
15185 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
15186 pRoamProfile->beaconInterval = params->beacon_interval;
15187 else {
15188 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015189 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015190 params->beacon_interval, pRoamProfile->beaconInterval);
15191 }
15192
15193 /* Set Channel */
15194 if (channelNum) {
15195 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015196 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015197 pRoamProfile->ChannelInfo.numOfChannels = 1;
15198 pHddStaCtx->conn_info.operationChannel = channelNum;
15199 pRoamProfile->ChannelInfo.ChannelList =
15200 &pHddStaCtx->conn_info.operationChannel;
15201 }
15202
15203 /* Initialize security parameters */
15204 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
15205 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015206 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015207 return status;
15208 }
15209
15210 /* Issue connect start */
15211 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
15212 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015213 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015214 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015215 operationChannel,
15216 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015217
15218 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015219 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015220 return status;
15221 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015222 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015223 return 0;
15224}
15225
15226/**
15227 * wlan_hdd_cfg80211_join_ibss() - join ibss
15228 * @wiphy: Pointer to wiphy
15229 * @dev: Pointer to network device
15230 * @param: Pointer to IBSS join parameters
15231 *
15232 * This function is used to create/join an IBSS network
15233 *
15234 * Return: 0 for success, non-zero for failure
15235 */
15236static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15237 struct net_device *dev,
15238 struct cfg80211_ibss_params *params)
15239{
15240 int ret = 0;
15241
15242 cds_ssr_protect(__func__);
15243 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
15244 cds_ssr_unprotect(__func__);
15245
15246 return ret;
15247}
15248
15249/**
15250 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
15251 * @wiphy: Pointer to wiphy
15252 * @dev: Pointer to network device
15253 *
15254 * This function is used to leave an IBSS network
15255 *
15256 * Return: 0 for success, non-zero for failure
15257 */
15258static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15259 struct net_device *dev)
15260{
15261 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15262 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15263 tCsrRoamProfile *pRoamProfile;
15264 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15265 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015266 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015267 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015268 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015269
15270 ENTER();
15271
Anurag Chouhan6d760662016-02-20 16:05:43 +053015272 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015273 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015274 return -EINVAL;
15275 }
15276
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015277 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015278 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015279 return -EINVAL;
15280 }
15281
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015282 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015283 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15284 pAdapter->sessionId,
15285 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15286 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015287 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015288 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015289
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015290 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015291 hdd_device_mode_to_string(pAdapter->device_mode),
15292 pAdapter->device_mode);
15293 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015294 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295 return -EIO;
15296 }
15297
15298 pRoamProfile = &pWextState->roamProfile;
15299
15300 /* Issue disconnect only if interface type is set to IBSS */
15301 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015302 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015303 return -EINVAL;
15304 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015305 /* Clearing add IE of beacon */
15306 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15307 sizeof(tSirMacAddr));
15308 updateIE.smeSessionId = pAdapter->sessionId;
15309 updateIE.ieBufferlength = 0;
15310 updateIE.pAdditionIEBuffer = NULL;
15311 updateIE.append = true;
15312 updateIE.notify = true;
15313 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15314 &updateIE,
15315 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015316 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015317 }
15318
15319 /* Reset WNI_CFG_PROBE_RSP Flags */
15320 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015321
15322 /* Issue Disconnect request */
15323 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15324 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15325 pAdapter->sessionId,
15326 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015327 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015328 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015329 hal_status);
15330 return -EAGAIN;
15331 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015332
15333 /* wait for mc thread to cleanup and then return to upper stack
15334 * so by the time upper layer calls the change interface, we are
15335 * all set to proceed further
15336 */
15337 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15338 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15339 if (!rc) {
15340 hdd_err("Failed to disconnect, timed out");
15341 return -ETIMEDOUT;
15342 }
15343
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015344 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015345 return 0;
15346}
15347
15348/**
15349 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15350 * @wiphy: Pointer to wiphy
15351 * @dev: Pointer to network device
15352 *
15353 * This function is used to leave an IBSS network
15354 *
15355 * Return: 0 for success, non-zero for failure
15356 */
15357static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15358 struct net_device *dev)
15359{
15360 int ret = 0;
15361
15362 cds_ssr_protect(__func__);
15363 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15364 cds_ssr_unprotect(__func__);
15365
15366 return ret;
15367}
15368
15369/**
15370 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15371 * @wiphy: Pointer to wiphy
15372 * @changed: Parameters changed
15373 *
15374 * This function is used to set the phy parameters. RTS Threshold/FRAG
15375 * Threshold/Retry Count etc.
15376 *
15377 * Return: 0 for success, non-zero for failure
15378 */
15379static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15380 u32 changed)
15381{
15382 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15383 tHalHandle hHal = pHddCtx->hHal;
15384 int status;
15385
15386 ENTER();
15387
Anurag Chouhan6d760662016-02-20 16:05:43 +053015388 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015389 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015390 return -EINVAL;
15391 }
15392
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015393 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015394 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15395 NO_SESSION, wiphy->rts_threshold));
15396 status = wlan_hdd_validate_context(pHddCtx);
15397
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015398 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015399 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015400
15401 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15402 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15403 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15404
15405 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15406 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015407 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015408 rts_threshold);
15409 return -EINVAL;
15410 }
15411
15412 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15413 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015414 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015415 rts_threshold);
15416 return -EIO;
15417 }
15418
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015419 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015420 }
15421
15422 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15423 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15424 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15425 wiphy->frag_threshold;
15426
15427 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15428 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015429 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015430 frag_threshold);
15431 return -EINVAL;
15432 }
15433
15434 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15435 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015436 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015437 frag_threshold);
15438 return -EIO;
15439 }
15440
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015441 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015442 }
15443
15444 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15445 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15446 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15447 wiphy->retry_short : wiphy->retry_long;
15448
15449 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15450 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015451 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015452 return -EINVAL;
15453 }
15454
15455 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15456 if (0 != sme_cfg_set_int(hHal,
15457 WNI_CFG_LONG_RETRY_LIMIT,
15458 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015459 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015460 retry_value);
15461 return -EIO;
15462 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015463 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015464 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15465 if (0 != sme_cfg_set_int(hHal,
15466 WNI_CFG_SHORT_RETRY_LIMIT,
15467 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015468 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015469 retry_value);
15470 return -EIO;
15471 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015472 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015473 }
15474 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015475 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015476 return 0;
15477}
15478
15479/**
15480 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15481 * @wiphy: Pointer to wiphy
15482 * @changed: Parameters changed
15483 *
15484 * Return: 0 for success, non-zero for failure
15485 */
15486static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15487{
15488 int ret;
15489
15490 cds_ssr_protect(__func__);
15491 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15492 cds_ssr_unprotect(__func__);
15493
15494 return ret;
15495}
15496
15497/**
15498 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15499 * key
15500 * @wiphy: Pointer to wiphy
15501 * @dev: Pointer to network device
15502 * @key_index: Key index
15503 *
15504 * Return: 0
15505 */
15506static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15507 struct net_device *netdev,
15508 u8 key_index)
15509{
15510 ENTER();
15511 return 0;
15512}
15513
15514/**
15515 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15516 * wlan_hdd_set_default_mgmt_key
15517 * @wiphy: pointer to wiphy
15518 * @netdev: pointer to net_device structure
15519 * @key_index: key index
15520 *
15521 * Return: 0 on success, error number on failure
15522 */
15523static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15524 struct net_device *netdev,
15525 u8 key_index)
15526{
15527 int ret;
15528
15529 cds_ssr_protect(__func__);
15530 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15531 cds_ssr_unprotect(__func__);
15532
15533 return ret;
15534}
15535
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015536/**
15537 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15538 * @wiphy: Pointer to wiphy
15539 * @dev: Pointer to network device
15540 * @params: Pointer to tx queue parameters
15541 *
15542 * Return: 0
15543 */
15544static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15545 struct net_device *dev,
15546 struct ieee80211_txq_params *params)
15547{
15548 ENTER();
15549 return 0;
15550}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015551
15552/**
15553 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15554 * @wiphy: pointer to wiphy
15555 * @netdev: pointer to net_device structure
15556 * @params: pointer to ieee80211_txq_params
15557 *
15558 * Return: 0 on success, error number on failure
15559 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015560static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15561 struct net_device *dev,
15562 struct ieee80211_txq_params *params)
15563{
15564 int ret;
15565
15566 cds_ssr_protect(__func__);
15567 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15568 cds_ssr_unprotect(__func__);
15569
15570 return ret;
15571}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015572
15573/**
15574 * __wlan_hdd_cfg80211_del_station() - delete station v2
15575 * @wiphy: Pointer to wiphy
15576 * @param: Pointer to delete station parameter
15577 *
15578 * Return: 0 for success, non-zero for failure
15579 */
15580static
15581int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15582 struct net_device *dev,
15583 struct tagCsrDelStaParams *pDelStaParams)
15584{
15585 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15586 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015587 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015588 hdd_hostapd_state_t *hapd_state;
15589 int status;
15590 uint8_t staId;
15591 uint8_t *mac;
15592
15593 ENTER();
15594
Anurag Chouhan6d760662016-02-20 16:05:43 +053015595 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015596 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015597 return -EINVAL;
15598 }
15599
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015600 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015601 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015602 return -EINVAL;
15603 }
15604
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015605 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015606 TRACE_CODE_HDD_CFG80211_DEL_STA,
15607 pAdapter->sessionId, pAdapter->device_mode));
15608
15609 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15610 status = wlan_hdd_validate_context(pHddCtx);
15611
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015612 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015613 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015614
15615 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15616
Krunal Sonib4326f22016-03-10 13:05:51 -080015617 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15618 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015619
15620 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15621 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015622 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015623 return 0;
15624 }
15625
Anurag Chouhanc5548422016-02-24 18:33:27 +053015626 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015627 uint16_t i;
15628 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15629 if ((pAdapter->aStaInfo[i].isUsed) &&
15630 (!pAdapter->aStaInfo[i].
15631 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015632 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015633 mac,
15634 pAdapter->aStaInfo[i].
15635 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015636 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015637 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15638 hdd_ipa_wlan_evt(pAdapter,
15639 pAdapter->
15640 aStaInfo[i].
15641 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015642 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015643 mac);
15644 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015645 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015646 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015647 MAC_ADDR_ARRAY(mac));
15648
15649 if (pHddCtx->dev_dfs_cac_status ==
15650 DFS_CAC_IN_PROGRESS)
15651 goto fn_end;
15652
Wei Song2f76f642016-11-18 16:32:53 +080015653 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015654 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015655 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015656 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015657 hdd_softap_sta_deauth(pAdapter,
15658 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015659 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015660 pAdapter->aStaInfo[i].
15661 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015662 qdf_status =
15663 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015664 &hapd_state->
15665 qdf_sta_disassoc_event,
15666 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015667 if (!QDF_IS_STATUS_SUCCESS(
15668 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015669 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015670 }
15671 }
15672 }
15673 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015674 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015675 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015676 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015677 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015678 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015679 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015680 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015681 MAC_ADDR_ARRAY(mac));
15682 return -ENOENT;
15683 }
15684
15685 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15686 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015687 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015688 }
15689
15690 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15691 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015692 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015693 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015694 MAC_ADDR_ARRAY(mac));
15695 return -ENOENT;
15696 }
15697
15698 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15699
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015700 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015701 MAC_ADDR_ARRAY(mac));
15702
15703 /* Case: SAP in ACS selected DFS ch and client connected
15704 * Now Radar detected. Then if random channel is another
15705 * DFS ch then new CAC is initiated and no TX allowed.
15706 * So do not send any mgmt frames as it will timeout
15707 * during CAC.
15708 */
15709
15710 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15711 goto fn_end;
15712
Wei Song2f76f642016-11-18 16:32:53 +080015713 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015714 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15715 (pAdapter), pAdapter->sessionId,
15716 (uint8_t *)&pDelStaParams->peerMacAddr,
15717 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015718 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015719 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015720 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015721 pAdapter->aStaInfo[staId].isDeauthInProgress =
15722 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015723 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015724 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015725 MAC_ADDR_ARRAY(mac));
15726 return -ENOENT;
15727 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015728 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015729 &hapd_state->
15730 qdf_sta_disassoc_event,
15731 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015732 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015733 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015734 }
15735 }
15736 }
15737
15738fn_end:
15739 EXIT();
15740 return 0;
15741}
15742
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015743#if defined(USE_CFG80211_DEL_STA_V2)
15744/**
15745 * wlan_hdd_del_station() - delete station wrapper
15746 * @adapter: pointer to the hdd adapter
15747 *
15748 * Return: None
15749 */
15750void wlan_hdd_del_station(hdd_adapter_t *adapter)
15751{
15752 struct station_del_parameters del_sta;
15753 del_sta.mac = NULL;
15754 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15755 del_sta.reason_code = eCsrForcedDeauthSta;
15756
15757 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15758 &del_sta);
15759}
15760#else
15761void wlan_hdd_del_station(hdd_adapter_t *adapter)
15762{
15763 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15764}
15765#endif
15766
15767#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015768/**
15769 * wlan_hdd_cfg80211_del_station() - delete station v2
15770 * @wiphy: Pointer to wiphy
15771 * @param: Pointer to delete station parameter
15772 *
15773 * Return: 0 for success, non-zero for failure
15774 */
15775int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15776 struct net_device *dev,
15777 struct station_del_parameters *param)
15778#else
15779/**
15780 * wlan_hdd_cfg80211_del_station() - delete station
15781 * @wiphy: Pointer to wiphy
15782 * @mac: Pointer to station mac address
15783 *
15784 * Return: 0 for success, non-zero for failure
15785 */
15786#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15787int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15788 struct net_device *dev,
15789 const uint8_t *mac)
15790#else
15791int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15792 struct net_device *dev,
15793 uint8_t *mac)
15794#endif
15795#endif
15796{
15797 int ret;
15798 struct tagCsrDelStaParams delStaParams;
15799
15800 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015801#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015802 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015803 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015804 return -EINVAL;
15805 }
15806 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15807 param->subtype, &delStaParams);
15808#else
15809 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15810 (SIR_MAC_MGMT_DEAUTH >> 4),
15811 &delStaParams);
15812#endif
15813 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15814 cds_ssr_unprotect(__func__);
15815
15816 return ret;
15817}
15818
15819/**
15820 * __wlan_hdd_cfg80211_add_station() - add station
15821 * @wiphy: Pointer to wiphy
15822 * @mac: Pointer to station mac address
15823 * @pmksa: Pointer to add station parameter
15824 *
15825 * Return: 0 for success, non-zero for failure
15826 */
15827static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15828 struct net_device *dev,
15829 const uint8_t *mac,
15830 struct station_parameters *params)
15831{
15832 int status = -EPERM;
15833#ifdef FEATURE_WLAN_TDLS
15834 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15835 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15836 u32 mask, set;
15837
15838 ENTER();
15839
Anurag Chouhan6d760662016-02-20 16:05:43 +053015840 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015841 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015842 return -EINVAL;
15843 }
15844
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015845 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015846 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015847 return -EINVAL;
15848 }
15849
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015850 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015851 TRACE_CODE_HDD_CFG80211_ADD_STA,
15852 pAdapter->sessionId, params->listen_interval));
15853
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015854 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015855 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015856
15857 mask = params->sta_flags_mask;
15858
15859 set = params->sta_flags_set;
15860
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015861 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015862 MAC_ADDR_ARRAY(mac));
15863
15864 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15865 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015866#if defined(CONVERGED_TDLS_ENABLE)
15867 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15868 dev, mac);
15869#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015870 status =
15871 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015872#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015873 }
15874 }
15875#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015876 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015877 return status;
15878}
15879
15880/**
15881 * wlan_hdd_cfg80211_add_station() - add station
15882 * @wiphy: Pointer to wiphy
15883 * @mac: Pointer to station mac address
15884 * @pmksa: Pointer to add station parameter
15885 *
15886 * Return: 0 for success, non-zero for failure
15887 */
15888#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15889static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15890 struct net_device *dev,
15891 const uint8_t *mac,
15892 struct station_parameters *params)
15893#else
15894static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15895 struct net_device *dev, uint8_t *mac,
15896 struct station_parameters *params)
15897#endif
15898{
15899 int ret;
15900
15901 cds_ssr_protect(__func__);
15902 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15903 cds_ssr_unprotect(__func__);
15904
15905 return ret;
15906}
15907
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015908/**
15909 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15910 * @wiphy: Pointer to wiphy
15911 * @dev: Pointer to network device
15912 * @pmksa: Pointer to set pmksa parameter
15913 *
15914 * Return: 0 for success, non-zero for failure
15915 */
15916static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15917 struct net_device *dev,
15918 struct cfg80211_pmksa *pmksa)
15919{
15920 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15921 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15922 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015923 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015924 int status;
15925 tPmkidCacheInfo pmk_id;
15926
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015927 ENTER();
15928
Anurag Chouhan6d760662016-02-20 16:05:43 +053015929 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015930 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015931 return -EINVAL;
15932 }
15933
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015934 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015935 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015936 return -EINVAL;
15937 }
15938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015939 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015940 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015941 return -EINVAL;
15942 }
15943
15944 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015945 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015946 pmksa->bssid, pmksa->pmkid);
15947 return -EINVAL;
15948 }
15949
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015950 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015951 MAC_ADDR_ARRAY(pmksa->bssid));
15952
15953 status = wlan_hdd_validate_context(pHddCtx);
15954
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015955 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015956 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015957
15958 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15959
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015960 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15961 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015962
15963 /* Add to the PMKSA ID Cache in CSR */
15964 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15965 &pmk_id, 1, false);
15966
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015967 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015968 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15969 pAdapter->sessionId, result));
15970
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015971 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015972 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015973}
15974
15975/**
15976 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15977 * @wiphy: Pointer to wiphy
15978 * @dev: Pointer to network device
15979 * @pmksa: Pointer to set pmksa parameter
15980 *
15981 * Return: 0 for success, non-zero for failure
15982 */
15983static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15984 struct net_device *dev,
15985 struct cfg80211_pmksa *pmksa)
15986{
15987 int ret;
15988
15989 cds_ssr_protect(__func__);
15990 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15991 cds_ssr_unprotect(__func__);
15992
15993 return ret;
15994}
15995
15996/**
15997 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15998 * @wiphy: Pointer to wiphy
15999 * @dev: Pointer to network device
16000 * @pmksa: Pointer to pmksa parameter
16001 *
16002 * Return: 0 for success, non-zero for failure
16003 */
16004static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16005 struct net_device *dev,
16006 struct cfg80211_pmksa *pmksa)
16007{
16008 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16009 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16010 tHalHandle halHandle;
16011 int status = 0;
16012
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016013 ENTER();
16014
Anurag Chouhan6d760662016-02-20 16:05:43 +053016015 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016016 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016017 return -EINVAL;
16018 }
16019
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016020 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16021 hdd_err("invalid session id: %d", pAdapter->sessionId);
16022 return -EINVAL;
16023 }
16024
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016025 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016026 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016027 return -EINVAL;
16028 }
16029
16030 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016031 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016032 return -EINVAL;
16033 }
16034
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016035 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016036 MAC_ADDR_ARRAY(pmksa->bssid));
16037
16038 status = wlan_hdd_validate_context(pHddCtx);
16039
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016040 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016041 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016042
16043 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16044
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016045 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016046 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
16047 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016048 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016049 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016050 sme_roam_del_pmkid_from_cache(halHandle,
16051 pAdapter->sessionId, pmksa->bssid,
16052 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016053 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016054 MAC_ADDR_ARRAY(pmksa->bssid));
16055 status = -EINVAL;
16056 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016057 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016058 return status;
16059}
16060
16061/**
16062 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16063 * @wiphy: Pointer to wiphy
16064 * @dev: Pointer to network device
16065 * @pmksa: Pointer to pmksa parameter
16066 *
16067 * Return: 0 for success, non-zero for failure
16068 */
16069static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16070 struct net_device *dev,
16071 struct cfg80211_pmksa *pmksa)
16072{
16073 int ret;
16074
16075 cds_ssr_protect(__func__);
16076 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
16077 cds_ssr_unprotect(__func__);
16078
16079 return ret;
16080
16081}
16082
16083/**
16084 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16085 * @wiphy: Pointer to wiphy
16086 * @dev: Pointer to network device
16087 *
16088 * Return: 0 for success, non-zero for failure
16089 */
16090static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16091 struct net_device *dev)
16092{
16093 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16094 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16095 tHalHandle halHandle;
16096 int status = 0;
16097
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016098 ENTER();
16099
Anurag Chouhan6d760662016-02-20 16:05:43 +053016100 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016101 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016102 return -EINVAL;
16103 }
16104
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016105 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16106 hdd_err("invalid session id: %d", pAdapter->sessionId);
16107 return -EINVAL;
16108 }
16109
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016110 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016111
16112 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16113 status = wlan_hdd_validate_context(pHddCtx);
16114
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016115 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016116 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016117
16118 /* Retrieve halHandle */
16119 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16120
16121 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016122 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016123 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
16124 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016125 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016126 status = -EINVAL;
16127 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016128 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016129 return status;
16130}
16131
16132/**
16133 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16134 * @wiphy: Pointer to wiphy
16135 * @dev: Pointer to network device
16136 *
16137 * Return: 0 for success, non-zero for failure
16138 */
16139static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16140 struct net_device *dev)
16141{
16142 int ret;
16143
16144 cds_ssr_protect(__func__);
16145 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
16146 cds_ssr_unprotect(__func__);
16147
16148 return ret;
16149}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016150
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016151#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016152/**
16153 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16154 * @wiphy: Pointer to wiphy
16155 * @dev: Pointer to network device
16156 * @ftie: Pointer to fast transition ie parameter
16157 *
16158 * Return: 0 for success, non-zero for failure
16159 */
16160static int
16161__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16162 struct net_device *dev,
16163 struct cfg80211_update_ft_ies_params *ftie)
16164{
16165 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16166 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16167 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16168 int status;
16169
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016170 ENTER();
16171
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016172 status = wlan_hdd_validate_context(hdd_ctx);
16173 if (status)
16174 return status;
16175
Anurag Chouhan6d760662016-02-20 16:05:43 +053016176 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016177 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016178 return -EINVAL;
16179 }
16180
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016181 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16182 hdd_err("invalid session id: %d", pAdapter->sessionId);
16183 return -EINVAL;
16184 }
16185
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016186 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016187 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
16188 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
16189 /* Added for debug on reception of Re-assoc Req. */
16190 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016191 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016192 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016193 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016194 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016195 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016196 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016197
16198 /* Pass the received FT IEs to SME */
16199 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
16200 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016201 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016202 return 0;
16203}
16204
16205/**
16206 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16207 * @wiphy: Pointer to wiphy
16208 * @dev: Pointer to network device
16209 * @ftie: Pointer to fast transition ie parameter
16210 *
16211 * Return: 0 for success, non-zero for failure
16212 */
16213static int
16214wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16215 struct net_device *dev,
16216 struct cfg80211_update_ft_ies_params *ftie)
16217{
16218 int ret;
16219
16220 cds_ssr_protect(__func__);
16221 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
16222 cds_ssr_unprotect(__func__);
16223
16224 return ret;
16225}
16226#endif
16227
Mukul Sharma3d36c392017-01-18 18:39:12 +053016228void wlan_hdd_cfg80211_update_replay_counter_callback(
16229 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
16230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016231{
Mukul Sharma3d36c392017-01-18 18:39:12 +053016232 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
16233 uint8_t temp_replay_counter[8];
16234 int i;
16235 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016236
16237 ENTER();
16238
Mukul Sharma3d36c392017-01-18 18:39:12 +053016239 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016240 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016241 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016242 }
16243
Mukul Sharma3d36c392017-01-18 18:39:12 +053016244 if (!gtk_rsp_param) {
16245 hdd_err("gtk_rsp_param is Null");
16246 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016247 }
16248
Mukul Sharma3d36c392017-01-18 18:39:12 +053016249 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016250 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016251 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016252 }
16253
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016254 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016255 gtk_rsp_param->replay_counter);
16256 /* convert little to big endian since supplicant works on big endian */
16257 p = (uint8_t *)&gtk_rsp_param->replay_counter;
16258 for (i = 0; i < 8; i++)
16259 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016260
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016261 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080016263 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016264 gtk_rsp_param->bssid.bytes,
16265 temp_replay_counter, GFP_KERNEL);
16266out:
16267 EXIT();
16268
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016269}
16270
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016271static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016272int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016273 struct net_device *dev,
16274 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016275{
16276 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016277 int result, i;
16278 struct pmo_gtk_req *gtk_req = NULL;
16279 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16280 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016281 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016282
16283 ENTER();
16284
Anurag Chouhan6d760662016-02-20 16:05:43 +053016285 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016286 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016287 result = -EINVAL;
16288 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016289 }
16290
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016291 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16292 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016293 result = -EINVAL;
16294 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016295 }
16296
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016297 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016298 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16299 pAdapter->sessionId, pAdapter->device_mode));
16300
Mukul Sharma3d36c392017-01-18 18:39:12 +053016301 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016302 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016303 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016304
Mukul Sharma3d36c392017-01-18 18:39:12 +053016305 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16306 if (!gtk_req) {
16307 hdd_err("cannot allocate gtk_req");
16308 result = -ENOMEM;
16309 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016310 }
16311
Mukul Sharma3d36c392017-01-18 18:39:12 +053016312 /* convert big to little endian since driver work on little endian */
16313 buf = (uint8_t *)&gtk_req->replay_counter;
16314 for (i = 0; i < 8; i++)
16315 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016316
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016317 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016318 gtk_req->replay_counter);
16319 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16320 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16321 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16322 if (status != QDF_STATUS_SUCCESS) {
16323 hdd_err("Failed to cache GTK Offload");
16324 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016325 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016326out:
16327 if (gtk_req)
16328 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016329 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016330
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016331 return result;
16332}
16333
16334/**
16335 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16336 * @wiphy: Pointer to wiphy
16337 * @dev: Pointer to network device
16338 * @data: Pointer to rekey data
16339 *
16340 * This function is used to offload GTK rekeying job to the firmware.
16341 *
16342 * Return: 0 for success, non-zero for failure
16343 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016344static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016345int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16346 struct net_device *dev,
16347 struct cfg80211_gtk_rekey_data *data)
16348{
16349 int ret;
16350
16351 cds_ssr_protect(__func__);
16352 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16353 cds_ssr_unprotect(__func__);
16354
16355 return ret;
16356}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016357
16358/**
16359 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16360 * @wiphy: Pointer to wiphy
16361 * @dev: Pointer to network device
16362 * @param: Pointer to access control parameter
16363 *
16364 * Return: 0 for success, non-zero for failure
16365 */
16366static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16367 struct net_device *dev,
16368 const struct cfg80211_acl_data *params)
16369{
16370 int i;
16371 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16372 hdd_hostapd_state_t *pHostapdState;
16373 tsap_Config_t *pConfig;
16374 v_CONTEXT_t p_cds_context = NULL;
16375 hdd_context_t *pHddCtx;
16376 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016377 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016378
16379 ENTER();
16380
Anurag Chouhan6d760662016-02-20 16:05:43 +053016381 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016382 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016383 return -EINVAL;
16384 }
16385
16386 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016387 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016388 return -EINVAL;
16389 }
16390
16391 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16392 status = wlan_hdd_validate_context(pHddCtx);
16393
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016394 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016395 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016396
16397 p_cds_context = pHddCtx->pcds_context;
16398 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16399
16400 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016401 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016402 return -EINVAL;
16403 }
16404
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016405 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016406 params->n_acl_entries);
16407
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016408 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016409 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16410 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016411 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016412 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16413
16414 /* default value */
16415 pConfig->num_accept_mac = 0;
16416 pConfig->num_deny_mac = 0;
16417
16418 /**
16419 * access control policy
16420 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16421 * listed in hostapd.deny file.
16422 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16423 * listed in hostapd.accept file.
16424 */
16425 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16426 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16427 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16428 params->acl_policy) {
16429 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16430 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016431 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016432 params->acl_policy);
16433 return -ENOTSUPP;
16434 }
16435
16436 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16437 pConfig->num_accept_mac = params->n_acl_entries;
16438 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016439 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016440 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016441 MAC_ADDR_ARRAY(
16442 params->mac_addrs[i].addr));
16443
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016444 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016445 params->mac_addrs[i].addr,
16446 sizeof(qcmacaddr));
16447 }
16448 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16449 pConfig->num_deny_mac = params->n_acl_entries;
16450 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016451 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016452 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016453 MAC_ADDR_ARRAY(
16454 params->mac_addrs[i].addr));
16455
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016456 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016457 params->mac_addrs[i].addr,
16458 sizeof(qcmacaddr));
16459 }
16460 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016461 qdf_status = wlansap_set_mac_acl(
16462 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016463 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016464 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016465 return -EINVAL;
16466 }
16467 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016468 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016469 hdd_device_mode_to_string(pAdapter->device_mode),
16470 pAdapter->device_mode);
16471 return -EINVAL;
16472 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016473 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016474 return 0;
16475}
16476
16477/**
16478 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16479 * __wlan_hdd_cfg80211_set_mac_acl
16480 * @wiphy: pointer to wiphy structure
16481 * @dev: pointer to net_device
16482 * @params: pointer to cfg80211_acl_data
16483 *
16484 * Return; 0 on success, error number otherwise
16485 */
16486static int
16487wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16488 struct net_device *dev,
16489 const struct cfg80211_acl_data *params)
16490{
16491 int ret;
16492
16493 cds_ssr_protect(__func__);
16494 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16495 cds_ssr_unprotect(__func__);
16496
16497 return ret;
16498}
16499
16500#ifdef WLAN_NL80211_TESTMODE
16501#ifdef FEATURE_WLAN_LPHB
16502/**
16503 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16504 * @pHddCtx: Pointer to hdd context
16505 * @lphbInd: Pointer to low power heart beat indication parameter
16506 *
16507 * Return: none
16508 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016509static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016510 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016511{
16512 struct sk_buff *skb;
16513
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016514 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016515
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016516 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016517 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016518
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016519 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016520 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016521 return;
16522 }
16523
16524 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016525 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016526 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016527 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016528 return;
16529 }
16530
16531 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016532 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016533 goto nla_put_failure;
16534 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016535 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016536 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016537 goto nla_put_failure;
16538 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016539 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16540 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016541 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016542 goto nla_put_failure;
16543 }
16544 cfg80211_testmode_event(skb, GFP_ATOMIC);
16545 return;
16546
16547nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016548 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016549 kfree_skb(skb);
16550
16551 return;
16552}
16553#endif /* FEATURE_WLAN_LPHB */
16554
16555/**
16556 * __wlan_hdd_cfg80211_testmode() - test mode
16557 * @wiphy: Pointer to wiphy
16558 * @data: Data pointer
16559 * @len: Data length
16560 *
16561 * Return: 0 for success, non-zero for failure
16562 */
16563static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16564 void *data, int len)
16565{
16566 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16567 int err;
16568 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16569
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016570 ENTER();
16571
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016572 err = wlan_hdd_validate_context(pHddCtx);
16573 if (err)
16574 return err;
16575
16576 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16577 len, wlan_hdd_tm_policy);
16578 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016579 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016580 return err;
16581 }
16582
16583 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016584 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016585 return -EINVAL;
16586 }
16587
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016588 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016589 TRACE_CODE_HDD_CFG80211_TESTMODE,
16590 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016591 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16592#ifdef FEATURE_WLAN_LPHB
16593 /* Low Power Heartbeat configuration request */
16594 case WLAN_HDD_TM_CMD_WLAN_HB:
16595 {
16596 int buf_len;
16597 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016598 struct pmo_lphb_req *hb_params = NULL;
16599 struct pmo_lphb_req *hb_params_temp = NULL;
16600 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016601
16602 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016603 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016604 return -EINVAL;
16605 }
16606
16607 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16608 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16609
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016610 hb_params_temp = (struct pmo_lphb_req *) buf;
16611 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16612 && (hb_params_temp->params.lphb_tcp_params.
16613 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016614 return -EINVAL;
16615
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016616 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16617 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016618 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016619 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016620 return -ENOMEM;
16621 }
16622
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016623 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016624 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16625 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016626 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016627 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016628 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016629
16630 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016631 return 0;
16632 }
16633#endif /* FEATURE_WLAN_LPHB */
16634
16635#if defined(QCA_WIFI_FTM)
16636 case WLAN_HDD_TM_CMD_WLAN_FTM:
16637 {
16638 int buf_len;
16639 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016640 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016641 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016642 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016643 return -EINVAL;
16644 }
16645
16646 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16647 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16648
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016649 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016650
16651 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16652
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016653 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016654 err = -EBUSY;
16655 break;
16656 }
16657#endif
16658
16659 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016660 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016661 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16662 return -EOPNOTSUPP;
16663 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016664 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016665 return err;
16666}
16667
16668/**
16669 * wlan_hdd_cfg80211_testmode() - test mode
16670 * @wiphy: Pointer to wiphy
16671 * @dev: Pointer to network device
16672 * @data: Data pointer
16673 * @len: Data length
16674 *
16675 * Return: 0 for success, non-zero for failure
16676 */
16677static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16678#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16679 struct wireless_dev *wdev,
16680#endif
16681 void *data, int len)
16682{
16683 int ret;
16684
16685 cds_ssr_protect(__func__);
16686 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16687 cds_ssr_unprotect(__func__);
16688
16689 return ret;
16690}
16691
16692#if defined(QCA_WIFI_FTM)
16693/**
16694 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16695 * @buf: Pointer to buffer
16696 * @buf_len: Buffer length
16697 *
16698 * Return: none
16699 */
16700void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16701{
16702 struct sk_buff *skb;
16703 hdd_context_t *hdd_ctx;
16704
16705 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016706 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016707 return;
16708 }
16709
Anurag Chouhan6d760662016-02-20 16:05:43 +053016710 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016711 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016712 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016713 return;
16714 }
16715
16716 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16717 buf_len, GFP_KERNEL);
16718 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016719 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016720 return;
16721 }
16722
16723 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16724 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16725 goto nla_put_failure;
16726
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016727 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016728
16729 cfg80211_testmode_event(skb, GFP_KERNEL);
16730 return;
16731
16732nla_put_failure:
16733 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016734 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016735}
16736#endif
16737#endif /* CONFIG_NL80211_TESTMODE */
16738
16739#ifdef QCA_HT_2040_COEX
16740/**
16741 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16742 * @wiphy: Pointer to wiphy
16743 * @dev: Pointer to network device
16744 * @chandef: Pointer to channel definition parameter
16745 *
16746 * Return: 0 for success, non-zero for failure
16747 */
16748static int
16749__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16750 struct net_device *dev,
16751 struct cfg80211_chan_def *chandef)
16752{
16753 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16754 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016755 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016756 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016757 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016758
Anurag Chouhan6d760662016-02-20 16:05:43 +053016759 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016760 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016761 return -EINVAL;
16762 }
16763
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016764 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16765 hdd_err("invalid session id: %d", pAdapter->sessionId);
16766 return -EINVAL;
16767 }
16768
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016769 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16770 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016771 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016772 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016773
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016774 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016775 sme_get_config_param(pHddCtx->hHal, &sme_config);
16776 switch (chandef->width) {
16777 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016778 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016779 if (sme_config.csrConfig.channelBondingMode24GHz !=
16780 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16781 sme_config.csrConfig.channelBondingMode24GHz =
16782 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16783 sme_update_config(pHddCtx->hHal, &sme_config);
16784 cbModeChange = true;
16785 }
16786 break;
16787
16788 case NL80211_CHAN_WIDTH_40:
16789 if (sme_config.csrConfig.channelBondingMode24GHz ==
16790 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16791 if (NL80211_CHAN_HT40MINUS ==
16792 cfg80211_get_chandef_type(chandef))
16793 sme_config.csrConfig.channelBondingMode24GHz =
16794 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16795 else
16796 sme_config.csrConfig.channelBondingMode24GHz =
16797 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16798 sme_update_config(pHddCtx->hHal, &sme_config);
16799 cbModeChange = true;
16800 }
16801 break;
16802
16803 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016804 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016805 return -EINVAL;
16806 }
16807
16808 if (!cbModeChange)
16809 return 0;
16810
Krunal Sonib4326f22016-03-10 13:05:51 -080016811 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016812 return 0;
16813
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016814 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016815 sme_config.csrConfig.channelBondingMode24GHz);
16816
16817 /* Change SAP ht2040 mode */
16818 status = hdd_set_sap_ht2040_mode(pAdapter,
16819 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016820 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016821 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016822 return -EINVAL;
16823 }
16824
16825 return 0;
16826}
16827
16828/**
16829 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16830 * @wiphy: Pointer to wiphy
16831 * @dev: Pointer to network device
16832 * @chandef: Pointer to channel definition parameter
16833 *
16834 * Return: 0 for success, non-zero for failure
16835 */
16836static int
16837wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16838 struct net_device *dev,
16839 struct cfg80211_chan_def *chandef)
16840{
16841 int ret;
16842
16843 cds_ssr_protect(__func__);
16844 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16845 cds_ssr_unprotect(__func__);
16846
16847 return ret;
16848}
16849#endif
16850
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016851#ifdef CHANNEL_SWITCH_SUPPORTED
16852/**
16853 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16854 * channel in SAP/GO
16855 * @wiphy: wiphy pointer
16856 * @dev: dev pointer.
16857 * @csa_params: Change channel params
16858 *
16859 * This function is called to switch channel in SAP/GO
16860 *
16861 * Return: 0 if success else return non zero
16862 */
16863static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16864 struct net_device *dev,
16865 struct cfg80211_csa_settings *csa_params)
16866{
16867 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16868 hdd_context_t *hdd_ctx;
16869 uint8_t channel;
16870 uint16_t freq;
16871 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016872 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016873
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016874 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016875 csa_params->chandef.chan->center_freq);
16876
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016877 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16878 hdd_err("invalid session id: %d", adapter->sessionId);
16879 return -EINVAL;
16880 }
16881
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016882 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16883 ret = wlan_hdd_validate_context(hdd_ctx);
16884
16885 if (0 != ret)
16886 return ret;
16887
Krunal Sonib4326f22016-03-10 13:05:51 -080016888 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16889 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016890 return -ENOTSUPP;
16891
16892 freq = csa_params->chandef.chan->center_freq;
16893 channel = cds_freq_to_chan(freq);
16894
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016895 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16896
16897 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016898 return ret;
16899}
16900
16901/**
16902 * wlan_hdd_cfg80211_channel_switch()- function to switch
16903 * channel in SAP/GO
16904 * @wiphy: wiphy pointer
16905 * @dev: dev pointer.
16906 * @csa_params: Change channel params
16907 *
16908 * This function is called to switch channel in SAP/GO
16909 *
16910 * Return: 0 if success else return non zero
16911 */
16912static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16913 struct net_device *dev,
16914 struct cfg80211_csa_settings *csa_params)
16915{
16916 int ret;
16917
16918 cds_ssr_protect(__func__);
16919 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16920 cds_ssr_unprotect(__func__);
16921 return ret;
16922}
16923#endif
16924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016925/**
16926 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16927 * translation from NL to policy manager type
16928 * @type: Generic connection mode type defined in NL
16929 *
16930 *
16931 * This function provides the type translation
16932 *
16933 * Return: cds_con_mode enum
16934 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016935enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016936 enum nl80211_iftype type)
16937{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016938 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016939 switch (type) {
16940 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016941 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016942 break;
16943 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016944 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016945 break;
16946 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016947 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016948 break;
16949 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016950 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016951 break;
16952 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016953 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016954 break;
16955 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016956 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016957 }
16958 return mode;
16959}
16960
16961/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016962 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16963 * @wiphy: Handle to struct wiphy to get handle to module context.
16964 * @chandef: Contains information about the capture channel to be set.
16965 *
16966 * This interface is called if and only if monitor mode interface alone is
16967 * active.
16968 *
16969 * Return: 0 success or error code on failure.
16970 */
16971static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16972 struct cfg80211_chan_def *chandef)
16973{
16974 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16975 hdd_adapter_t *adapter;
16976 hdd_station_ctx_t *sta_ctx;
16977 struct hdd_mon_set_ch_info *ch_info;
16978 QDF_STATUS status;
16979 tHalHandle hal_hdl;
16980 struct qdf_mac_addr bssid;
16981 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016982 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016983 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016984 int ret;
16985 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16986
16987 ENTER();
16988
16989 ret = wlan_hdd_validate_context(hdd_ctx);
16990 if (ret)
16991 return ret;
16992
16993 hal_hdl = hdd_ctx->hHal;
16994
16995 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16996 if (!adapter)
16997 return -EIO;
16998
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016999 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017000 adapter->dev->name, chan_num, chandef->chan->center_freq);
17001
17002 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17003 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017004 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
17005 roam_profile.ChannelInfo.numOfChannels = 1;
17006 roam_profile.phyMode = ch_info->phy_mode;
17007 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017008 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017009
17010 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
17011 QDF_MAC_ADDR_SIZE);
17012
17013 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017014 /*
17015 * CDS api expects secondary channel for calculating
17016 * the channel params
17017 */
17018 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017019 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017020 if (chan_num >= 1 && chan_num <= 5)
17021 sec_ch = chan_num + 4;
17022 else if (chan_num >= 6 && chan_num <= 13)
17023 sec_ch = chan_num - 4;
17024 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017025 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
17026 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017027 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
17028 &roam_profile);
17029 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017030 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017031 status);
17032 ret = qdf_status_to_os_return(status);
17033 return ret;
17034 }
17035 EXIT();
17036 return 0;
17037}
17038
17039/**
17040 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17041 * @wiphy: Handle to struct wiphy to get handle to module context.
17042 * @chandef: Contains information about the capture channel to be set.
17043 *
17044 * This interface is called if and only if monitor mode interface alone is
17045 * active.
17046 *
17047 * Return: 0 success or error code on failure.
17048 */
17049static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17050 struct cfg80211_chan_def *chandef)
17051{
17052 int ret;
17053
17054 cds_ssr_protect(__func__);
17055 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
17056 cds_ssr_unprotect(__func__);
17057 return ret;
17058}
17059
17060/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017061 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
17062 * @adapter: pointer to adapter
17063 *
17064 * Wrapper function to clear link layer stats.
17065 * return - void
17066 */
17067void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
17068{
17069 tSirLLStatsClearReq link_layer_stats_clear_req;
17070 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
17071
Mukul Sharma491021c2016-09-29 21:39:19 +053017072 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
17073 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017074 link_layer_stats_clear_req.stopReq = 0;
17075 link_layer_stats_clear_req.reqId = 1;
17076 link_layer_stats_clear_req.staId = adapter->sessionId;
17077 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
17078
17079 return;
17080}
17081
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017082/**
17083 * hdd_process_defer_disconnect() - Handle the deferred disconnect
17084 * @adapter: HDD Adapter
17085 *
17086 * If roaming is in progress and there is a request to
17087 * disconnect the session, then it is deferred. Once
17088 * roaming is complete/aborted, then this routine is
17089 * used to resume the disconnect that was deferred
17090 *
17091 * Return: None
17092 */
17093void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
17094{
17095 switch (adapter->defer_disconnect) {
17096 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
17097 adapter->defer_disconnect = 0;
17098 wlan_hdd_disconnect(adapter,
17099 adapter->cfg80211_disconnect_reason);
17100 break;
17101 case DEFER_DISCONNECT_TRY_DISCONNECT:
17102 wlan_hdd_try_disconnect(adapter);
17103 adapter->defer_disconnect = 0;
17104 break;
17105 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017106 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017107 adapter->defer_disconnect);
17108 break;
17109 }
17110}
17111
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017112#define CNT_DIFF(cur, prev) \
17113 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
17114#define MAX_COUNT 0xffffffff
17115static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
17116 struct scan_chan_info *chan,
17117 struct scan_chan_info *info, uint32_t cmd_flag)
17118{
17119 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
17120 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
17121 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
17122
17123 mutex_lock(&hdd_ctx->chan_info_lock);
17124
17125 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
17126 qdf_mem_zero(chan, sizeof(*chan));
17127
17128 chan->freq = info->freq;
17129 chan->noise_floor = info->noise_floor;
17130 chan->clock_freq = info->clock_freq;
17131 chan->cmd_flag = info->cmd_flag;
17132 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
17133
17134 chan->rx_clear_count =
17135 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
17136
17137 chan->tx_frame_count =
17138 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
17139
17140 mutex_unlock(&hdd_ctx->chan_info_lock);
17141
17142}
17143#undef CNT_DIFF
17144#undef MAX_COUNT
17145
17146/**
17147 * wlan_hdd_chan_info_cb() - channel info callback
17148 * @chan_info: struct scan_chan_info
17149 *
17150 * Store channel info into HDD context
17151 *
17152 * Return: None.
17153 */
17154static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
17155{
17156 hdd_context_t *hdd_ctx;
17157 struct scan_chan_info *chan;
17158 uint8_t idx;
17159
17160 ENTER();
17161
17162 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17163 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
17164 hdd_err("hdd_ctx is invalid");
17165 return;
17166 }
17167
17168 if (!hdd_ctx->chan_info) {
17169 hdd_err("chan_info is NULL");
17170 return;
17171 }
17172
17173 chan = hdd_ctx->chan_info;
17174 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
17175 if (chan[idx].freq == info->freq) {
17176 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
17177 info->cmd_flag);
17178 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
17179 chan[idx].cmd_flag, chan[idx].freq,
17180 chan[idx].noise_floor,
17181 chan[idx].cycle_count, chan[idx].rx_clear_count,
17182 chan[idx].clock_freq, chan[idx].cmd_flag,
17183 chan[idx].tx_frame_count, idx);
17184 if (chan[idx].freq == 0)
17185 break;
17186
17187 }
17188 }
17189
17190 EXIT();
17191}
17192
17193/**
17194 * wlan_hdd_init_chan_info() - init chan info in hdd context
17195 * @hdd_ctx: HDD context pointer
17196 *
17197 * Return: none
17198 */
17199void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
17200{
17201 uint8_t num_2g, num_5g, index = 0;
17202
17203 if (!hdd_ctx->config->fEnableSNRMonitoring) {
17204 hdd_info("SNR monitoring is disabled");
17205 return;
17206 }
17207
17208 hdd_ctx->chan_info =
17209 qdf_mem_malloc(sizeof(struct scan_chan_info)
17210 * QDF_MAX_NUM_CHAN);
17211 if (hdd_ctx->chan_info == NULL) {
17212 hdd_err("Failed to malloc for chan info");
17213 return;
17214 }
17215 mutex_init(&hdd_ctx->chan_info_lock);
17216
17217 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
17218 for (; index < num_2g; index++) {
17219 hdd_ctx->chan_info[index].freq =
17220 hdd_channels_2_4_ghz[index].center_freq;
17221 }
17222
17223 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
17224 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017225 if (WLAN_REG_IS_11P_CH(
17226 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017227 continue;
17228 hdd_ctx->chan_info[index].freq =
17229 hdd_channels_5_ghz[index - num_2g].center_freq;
17230 }
17231 sme_set_chan_info_callback(hdd_ctx->hHal,
17232 &wlan_hdd_chan_info_cb);
17233}
17234
17235/**
17236 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
17237 * @hdd_ctx: hdd context pointer
17238 *
17239 * Return: none
17240 */
17241void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
17242{
17243 struct scan_chan_info *chan;
17244
17245 chan = hdd_ctx->chan_info;
17246 hdd_ctx->chan_info = NULL;
17247 if (chan)
17248 qdf_mem_free(chan);
17249}
17250
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017251/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017252 * struct cfg80211_ops - cfg80211_ops
17253 *
17254 * @add_virtual_intf: Add virtual interface
17255 * @del_virtual_intf: Delete virtual interface
17256 * @change_virtual_intf: Change virtual interface
17257 * @change_station: Change station
17258 * @add_beacon: Add beacon in sap mode
17259 * @del_beacon: Delete beacon in sap mode
17260 * @set_beacon: Set beacon in sap mode
17261 * @start_ap: Start ap
17262 * @change_beacon: Change beacon
17263 * @stop_ap: Stop ap
17264 * @change_bss: Change bss
17265 * @add_key: Add key
17266 * @get_key: Get key
17267 * @del_key: Delete key
17268 * @set_default_key: Set default key
17269 * @set_channel: Set channel
17270 * @scan: Scan
17271 * @connect: Connect
17272 * @disconnect: Disconnect
17273 * @join_ibss = Join ibss
17274 * @leave_ibss = Leave ibss
17275 * @set_wiphy_params = Set wiphy params
17276 * @set_tx_power = Set tx power
17277 * @get_tx_power = get tx power
17278 * @remain_on_channel = Remain on channel
17279 * @cancel_remain_on_channel = Cancel remain on channel
17280 * @mgmt_tx = Tx management frame
17281 * @mgmt_tx_cancel_wait = Cancel management tx wait
17282 * @set_default_mgmt_key = Set default management key
17283 * @set_txq_params = Set tx queue parameters
17284 * @get_station = Get station
17285 * @set_power_mgmt = Set power management
17286 * @del_station = Delete station
17287 * @add_station = Add station
17288 * @set_pmksa = Set pmksa
17289 * @del_pmksa = Delete pmksa
17290 * @flush_pmksa = Flush pmksa
17291 * @update_ft_ies = Update FT IEs
17292 * @tdls_mgmt = Tdls management
17293 * @tdls_oper = Tdls operation
17294 * @set_rekey_data = Set rekey data
17295 * @sched_scan_start = Scheduled scan start
17296 * @sched_scan_stop = Scheduled scan stop
17297 * @resume = Resume wlan
17298 * @suspend = Suspend wlan
17299 * @set_mac_acl = Set mac acl
17300 * @testmode_cmd = Test mode command
17301 * @set_ap_chanwidth = Set AP channel bandwidth
17302 * @dump_survey = Dump survey
17303 * @key_mgmt_set_pmk = Set pmk key management
17304 */
17305static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17306 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17307 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17308 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17309 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017310 .start_ap = wlan_hdd_cfg80211_start_ap,
17311 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17312 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017313 .change_bss = wlan_hdd_cfg80211_change_bss,
17314 .add_key = wlan_hdd_cfg80211_add_key,
17315 .get_key = wlan_hdd_cfg80211_get_key,
17316 .del_key = wlan_hdd_cfg80211_del_key,
17317 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17318 .scan = wlan_hdd_cfg80211_scan,
17319 .connect = wlan_hdd_cfg80211_connect,
17320 .disconnect = wlan_hdd_cfg80211_disconnect,
17321 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17322 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17323 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17324 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17325 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17326 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17327 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17328 .mgmt_tx = wlan_hdd_mgmt_tx,
17329 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17330 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17331 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017332 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017333 .get_station = wlan_hdd_cfg80211_get_station,
17334 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17335 .del_station = wlan_hdd_cfg80211_del_station,
17336 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017337 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17338 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17339 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017340#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017341 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17342#endif
17343#ifdef FEATURE_WLAN_TDLS
17344 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17345 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17346#endif
17347#ifdef WLAN_FEATURE_GTK_OFFLOAD
17348 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17349#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17350#ifdef FEATURE_WLAN_SCAN_PNO
17351 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17352 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17353#endif /*FEATURE_WLAN_SCAN_PNO */
17354 .resume = wlan_hdd_cfg80211_resume_wlan,
17355 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17356 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17357#ifdef WLAN_NL80211_TESTMODE
17358 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17359#endif
17360#ifdef QCA_HT_2040_COEX
17361 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17362#endif
17363 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017364#ifdef CHANNEL_SWITCH_SUPPORTED
17365 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17366#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017367 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017368#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17369 defined(CFG80211_ABORT_SCAN)
17370 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17371#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017372};