blob: 32624809eb5944141ca2fd3c74d983c86a603bdb [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080081#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080082#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083
84#ifdef FEATURE_WLAN_EXTSCAN
85#include "wlan_hdd_ext_scan.h"
86#endif
87
88#ifdef WLAN_FEATURE_LINK_LAYER_STATS
89#include "wlan_hdd_stats.h"
90#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080091#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080092#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#include "qwlan_version.h"
94#include "wlan_hdd_memdump.h"
95
96#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070097#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +0530100#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700101#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700102#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530103#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800104#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800105#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800106
Leo Changfdb45c32016-10-28 11:09:23 -0700107#include <cdp_txrx_cmn.h>
108#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800109#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530110#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800111#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530112#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700113#include "wlan_reg_ucfg_api.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115#define g_mode_rates_size (12)
116#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800117#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
118 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
119
120/*
121 * Android CTS verifier needs atleast this much wait time (in msec)
122 */
123#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
124
125/*
126 * Refer @tCfgProtection structure for definition of the bit map.
127 * below value is obtained by setting the following bit-fields.
128 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
129 */
130#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
131
132#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700133 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134 .center_freq = (freq), \
135 .hw_value = (chan), \
136 .flags = (flag), \
137 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800138 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139}
140
141#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700142 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143 .center_freq = (freq), \
144 .hw_value = (chan), \
145 .flags = (flag), \
146 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800147 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148}
149
150#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
151 { \
152 .bitrate = rate, \
153 .hw_value = rate_id, \
154 .flags = flag, \
155 }
156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
158#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159
160#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800161
Agrawal Ashish65634612016-08-18 13:24:32 +0530162#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
163 mode <= DFS_MODE_DEPRIORITIZE))
164#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
165 || (channel >= 36 && channel <= 184))
166
Peng Xu4d67c8f2015-10-16 16:02:26 -0700167#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530168#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700169
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170static const u32 hdd_cipher_suites[] = {
171 WLAN_CIPHER_SUITE_WEP40,
172 WLAN_CIPHER_SUITE_WEP104,
173 WLAN_CIPHER_SUITE_TKIP,
174#ifdef FEATURE_WLAN_ESE
175#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
176#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
177 WLAN_CIPHER_SUITE_BTK,
178 WLAN_CIPHER_SUITE_KRK,
179 WLAN_CIPHER_SUITE_CCMP,
180#else
181 WLAN_CIPHER_SUITE_CCMP,
182#endif
183#ifdef FEATURE_WLAN_WAPI
184 WLAN_CIPHER_SUITE_SMS4,
185#endif
186#ifdef WLAN_FEATURE_11W
187 WLAN_CIPHER_SUITE_AES_CMAC,
188#endif
189};
190
Abhishek Singhf512bf32016-05-04 16:47:46 +0530191static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192 HDD2GHZCHAN(2412, 1, 0),
193 HDD2GHZCHAN(2417, 2, 0),
194 HDD2GHZCHAN(2422, 3, 0),
195 HDD2GHZCHAN(2427, 4, 0),
196 HDD2GHZCHAN(2432, 5, 0),
197 HDD2GHZCHAN(2437, 6, 0),
198 HDD2GHZCHAN(2442, 7, 0),
199 HDD2GHZCHAN(2447, 8, 0),
200 HDD2GHZCHAN(2452, 9, 0),
201 HDD2GHZCHAN(2457, 10, 0),
202 HDD2GHZCHAN(2462, 11, 0),
203 HDD2GHZCHAN(2467, 12, 0),
204 HDD2GHZCHAN(2472, 13, 0),
205 HDD2GHZCHAN(2484, 14, 0),
206};
207
Abhishek Singhf512bf32016-05-04 16:47:46 +0530208static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209 HDD5GHZCHAN(5180, 36, 0),
210 HDD5GHZCHAN(5200, 40, 0),
211 HDD5GHZCHAN(5220, 44, 0),
212 HDD5GHZCHAN(5240, 48, 0),
213 HDD5GHZCHAN(5260, 52, 0),
214 HDD5GHZCHAN(5280, 56, 0),
215 HDD5GHZCHAN(5300, 60, 0),
216 HDD5GHZCHAN(5320, 64, 0),
217 HDD5GHZCHAN(5500, 100, 0),
218 HDD5GHZCHAN(5520, 104, 0),
219 HDD5GHZCHAN(5540, 108, 0),
220 HDD5GHZCHAN(5560, 112, 0),
221 HDD5GHZCHAN(5580, 116, 0),
222 HDD5GHZCHAN(5600, 120, 0),
223 HDD5GHZCHAN(5620, 124, 0),
224 HDD5GHZCHAN(5640, 128, 0),
225 HDD5GHZCHAN(5660, 132, 0),
226 HDD5GHZCHAN(5680, 136, 0),
227 HDD5GHZCHAN(5700, 140, 0),
228 HDD5GHZCHAN(5720, 144, 0),
229 HDD5GHZCHAN(5745, 149, 0),
230 HDD5GHZCHAN(5765, 153, 0),
231 HDD5GHZCHAN(5785, 157, 0),
232 HDD5GHZCHAN(5805, 161, 0),
233 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800234 HDD5GHZCHAN(5852, 170, 0),
235 HDD5GHZCHAN(5855, 171, 0),
236 HDD5GHZCHAN(5860, 172, 0),
237 HDD5GHZCHAN(5865, 173, 0),
238 HDD5GHZCHAN(5870, 174, 0),
239 HDD5GHZCHAN(5875, 175, 0),
240 HDD5GHZCHAN(5880, 176, 0),
241 HDD5GHZCHAN(5885, 177, 0),
242 HDD5GHZCHAN(5890, 178, 0),
243 HDD5GHZCHAN(5895, 179, 0),
244 HDD5GHZCHAN(5900, 180, 0),
245 HDD5GHZCHAN(5905, 181, 0),
246 HDD5GHZCHAN(5910, 182, 0),
247 HDD5GHZCHAN(5915, 183, 0),
248 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800249};
250
251static struct ieee80211_rate g_mode_rates[] = {
252 HDD_G_MODE_RATETAB(10, 0x1, 0),
253 HDD_G_MODE_RATETAB(20, 0x2, 0),
254 HDD_G_MODE_RATETAB(55, 0x4, 0),
255 HDD_G_MODE_RATETAB(110, 0x8, 0),
256 HDD_G_MODE_RATETAB(60, 0x10, 0),
257 HDD_G_MODE_RATETAB(90, 0x20, 0),
258 HDD_G_MODE_RATETAB(120, 0x40, 0),
259 HDD_G_MODE_RATETAB(180, 0x80, 0),
260 HDD_G_MODE_RATETAB(240, 0x100, 0),
261 HDD_G_MODE_RATETAB(360, 0x200, 0),
262 HDD_G_MODE_RATETAB(480, 0x400, 0),
263 HDD_G_MODE_RATETAB(540, 0x800, 0),
264};
265
266static struct ieee80211_rate a_mode_rates[] = {
267 HDD_G_MODE_RATETAB(60, 0x10, 0),
268 HDD_G_MODE_RATETAB(90, 0x20, 0),
269 HDD_G_MODE_RATETAB(120, 0x40, 0),
270 HDD_G_MODE_RATETAB(180, 0x80, 0),
271 HDD_G_MODE_RATETAB(240, 0x100, 0),
272 HDD_G_MODE_RATETAB(360, 0x200, 0),
273 HDD_G_MODE_RATETAB(480, 0x400, 0),
274 HDD_G_MODE_RATETAB(540, 0x800, 0),
275};
276
277static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530278 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700280 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281 .bitrates = g_mode_rates,
282 .n_bitrates = g_mode_rates_size,
283 .ht_cap.ht_supported = 1,
284 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
285 | IEEE80211_HT_CAP_GRN_FLD
286 | IEEE80211_HT_CAP_DSSSCCK40
287 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
288 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
289 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
290 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
291 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
292 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
293 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
294};
295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530297 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800298 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700299 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800300 .bitrates = a_mode_rates,
301 .n_bitrates = a_mode_rates_size,
302 .ht_cap.ht_supported = 1,
303 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
304 | IEEE80211_HT_CAP_GRN_FLD
305 | IEEE80211_HT_CAP_DSSSCCK40
306 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
307 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
308 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
309 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
310 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
311 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
312 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
313 .vht_cap.vht_supported = 1,
314};
315
316/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800317 * TX/RX direction for each kind of interface
318 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319static const struct ieee80211_txrx_stypes
320 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
321 [NL80211_IFTYPE_STATION] = {
322 .tx = 0xffff,
323 .rx = BIT(SIR_MAC_MGMT_ACTION) |
324 BIT(SIR_MAC_MGMT_PROBE_REQ),
325 },
326 [NL80211_IFTYPE_AP] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
336 [NL80211_IFTYPE_ADHOC] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
339 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
340 BIT(SIR_MAC_MGMT_PROBE_REQ) |
341 BIT(SIR_MAC_MGMT_DISASSOC) |
342 BIT(SIR_MAC_MGMT_AUTH) |
343 BIT(SIR_MAC_MGMT_DEAUTH) |
344 BIT(SIR_MAC_MGMT_ACTION),
345 },
346 [NL80211_IFTYPE_P2P_CLIENT] = {
347 .tx = 0xffff,
348 .rx = BIT(SIR_MAC_MGMT_ACTION) |
349 BIT(SIR_MAC_MGMT_PROBE_REQ),
350 },
351 [NL80211_IFTYPE_P2P_GO] = {
352 /* This is also same as for SoftAP */
353 .tx = 0xffff,
354 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
355 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
356 BIT(SIR_MAC_MGMT_PROBE_REQ) |
357 BIT(SIR_MAC_MGMT_DISASSOC) |
358 BIT(SIR_MAC_MGMT_AUTH) |
359 BIT(SIR_MAC_MGMT_DEAUTH) |
360 BIT(SIR_MAC_MGMT_ACTION),
361 },
362};
363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800364/* Interface limits and combinations registered by the driver */
365
366/* STA ( + STA ) combination */
367static const struct ieee80211_iface_limit
368 wlan_hdd_sta_iface_limit[] = {
369 {
370 .max = 3, /* p2p0 is a STA as well */
371 .types = BIT(NL80211_IFTYPE_STATION),
372 },
373};
374
375/* ADHOC (IBSS) limit */
376static const struct ieee80211_iface_limit
377 wlan_hdd_adhoc_iface_limit[] = {
378 {
379 .max = 1,
380 .types = BIT(NL80211_IFTYPE_STATION),
381 },
382 {
383 .max = 1,
384 .types = BIT(NL80211_IFTYPE_ADHOC),
385 },
386};
387
388/* AP ( + AP ) combination */
389static const struct ieee80211_iface_limit
390 wlan_hdd_ap_iface_limit[] = {
391 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530392 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 .types = BIT(NL80211_IFTYPE_AP),
394 },
395};
396
397/* P2P limit */
398static const struct ieee80211_iface_limit
399 wlan_hdd_p2p_iface_limit[] = {
400 {
401 .max = 1,
402 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
403 },
404 {
405 .max = 1,
406 .types = BIT(NL80211_IFTYPE_P2P_GO),
407 },
408};
409
410static const struct ieee80211_iface_limit
411 wlan_hdd_sta_ap_iface_limit[] = {
412 {
413 /* We need 1 extra STA interface for OBSS scan when SAP starts
414 * with HT40 in STA+SAP concurrency mode
415 */
416 .max = (1 + SAP_MAX_OBSS_STA_CNT),
417 .types = BIT(NL80211_IFTYPE_STATION),
418 },
419 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530420 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 .types = BIT(NL80211_IFTYPE_AP),
422 },
423};
424
425/* STA + P2P combination */
426static const struct ieee80211_iface_limit
427 wlan_hdd_sta_p2p_iface_limit[] = {
428 {
429 /* One reserved for dedicated P2PDEV usage */
430 .max = 2,
431 .types = BIT(NL80211_IFTYPE_STATION)
432 },
433 {
434 /* Support for two identical (GO + GO or CLI + CLI)
435 * or dissimilar (GO + CLI) P2P interfaces
436 */
437 .max = 2,
438 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
439 },
440};
441
442/* STA + AP + P2PGO combination */
443static const struct ieee80211_iface_limit
444wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
445 /* Support for AP+P2PGO interfaces */
446 {
447 .max = 2,
448 .types = BIT(NL80211_IFTYPE_STATION)
449 },
450 {
451 .max = 1,
452 .types = BIT(NL80211_IFTYPE_P2P_GO)
453 },
454 {
455 .max = 1,
456 .types = BIT(NL80211_IFTYPE_AP)
457 }
458};
459
460/* SAP + P2P combination */
461static const struct ieee80211_iface_limit
462wlan_hdd_sap_p2p_iface_limit[] = {
463 {
464 /* 1 dedicated for p2p0 which is a STA type */
465 .max = 1,
466 .types = BIT(NL80211_IFTYPE_STATION)
467 },
468 {
469 /* The p2p interface in SAP+P2P can be GO/CLI.
470 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
471 */
472 .max = 1,
473 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
474 },
475 {
476 /* SAP+GO to support only one SAP interface */
477 .max = 1,
478 .types = BIT(NL80211_IFTYPE_AP)
479 }
480};
481
482/* P2P + P2P combination */
483static const struct ieee80211_iface_limit
484wlan_hdd_p2p_p2p_iface_limit[] = {
485 {
486 /* 1 dedicated for p2p0 which is a STA type */
487 .max = 1,
488 .types = BIT(NL80211_IFTYPE_STATION)
489 },
490 {
491 /* The p2p interface in P2P+P2P can be GO/CLI.
492 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
493 */
494 .max = 2,
495 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
496 },
497};
498
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700499static const struct ieee80211_iface_limit
500 wlan_hdd_mon_iface_limit[] = {
501 {
502 .max = 3, /* Monitor interface */
503 .types = BIT(NL80211_IFTYPE_MONITOR),
504 },
505};
506
507static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 wlan_hdd_iface_combination[] = {
509 /* STA */
510 {
511 .limits = wlan_hdd_sta_iface_limit,
512 .num_different_channels = 2,
513 .max_interfaces = 3,
514 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
515 },
516 /* ADHOC */
517 {
518 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700519 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 .max_interfaces = 2,
521 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
522 },
523 /* AP */
524 {
525 .limits = wlan_hdd_ap_iface_limit,
526 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530527 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
529 },
530 /* P2P */
531 {
532 .limits = wlan_hdd_p2p_iface_limit,
533 .num_different_channels = 2,
534 .max_interfaces = 2,
535 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
536 },
537 /* STA + AP */
538 {
539 .limits = wlan_hdd_sta_ap_iface_limit,
540 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530541 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
543 .beacon_int_infra_match = true,
544 },
545 /* STA + P2P */
546 {
547 .limits = wlan_hdd_sta_p2p_iface_limit,
548 .num_different_channels = 2,
549 /* one interface reserved for P2PDEV dedicated usage */
550 .max_interfaces = 4,
551 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
552 .beacon_int_infra_match = true,
553 },
554 /* STA + P2P GO + SAP */
555 {
556 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
557 /* we can allow 3 channels for three different persona
558 * but due to firmware limitation, allow max 2 concrnt channels.
559 */
560 .num_different_channels = 2,
561 /* one interface reserved for P2PDEV dedicated usage */
562 .max_interfaces = 4,
563 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
564 .beacon_int_infra_match = true,
565 },
566 /* SAP + P2P */
567 {
568 .limits = wlan_hdd_sap_p2p_iface_limit,
569 .num_different_channels = 2,
570 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
571 .max_interfaces = 3,
572 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
573 .beacon_int_infra_match = true,
574 },
575 /* P2P + P2P */
576 {
577 .limits = wlan_hdd_p2p_p2p_iface_limit,
578 .num_different_channels = 2,
579 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
580 .max_interfaces = 3,
581 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
582 .beacon_int_infra_match = true,
583 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530584 /* Monitor */
585 {
586 .limits = wlan_hdd_mon_iface_limit,
587 .max_interfaces = 3,
588 .num_different_channels = 2,
589 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
590 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592
593static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594
595#ifdef WLAN_NL80211_TESTMODE
596enum wlan_hdd_tm_attr {
597 WLAN_HDD_TM_ATTR_INVALID = 0,
598 WLAN_HDD_TM_ATTR_CMD = 1,
599 WLAN_HDD_TM_ATTR_DATA = 2,
600 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
601 WLAN_HDD_TM_ATTR_TYPE = 4,
602 /* keep last */
603 WLAN_HDD_TM_ATTR_AFTER_LAST,
604 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
605};
606
607enum wlan_hdd_tm_cmd {
608 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
609 WLAN_HDD_TM_CMD_WLAN_HB = 1,
610};
611
612#define WLAN_HDD_TM_DATA_MAX_LEN 5000
613
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530614enum wlan_hdd_vendor_ie_access_policy {
615 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
616 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
617};
618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800619static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
620 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
621 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
622 .len = WLAN_HDD_TM_DATA_MAX_LEN},
623};
624#endif /* WLAN_NL80211_TESTMODE */
625
626#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
627static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
628 .flags = WIPHY_WOWLAN_MAGIC_PKT,
629 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
630 .pattern_min_len = 1,
631 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
632};
633#endif
634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530636 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
637 * @flags: Pointer to the flags to Add channel switch flag.
638 *
639 * This Function adds Channel Switch support flag, if channel switch is
640 * supported by kernel.
641 * Return: void.
642 */
643#ifdef CHANNEL_SWITCH_SUPPORTED
644static inline void hdd_add_channel_switch_support(uint32_t *flags)
645{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800646 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530647 return;
648}
649#else
650static inline void hdd_add_channel_switch_support(uint32_t *flags)
651{
652 return;
653}
654#endif
655
Manikandan Mohan22b83722015-12-15 15:03:23 -0800656#ifdef FEATURE_WLAN_TDLS
657
658/* TDLS capabilities params */
659#define PARAM_MAX_TDLS_SESSION \
660 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
661#define PARAM_TDLS_FEATURE_SUPPORT \
662 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
663
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530664/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
666 * @wiphy: WIPHY structure pointer
667 * @wdev: Wireless device structure pointer
668 * @data: Pointer to the data received
669 * @data_len: Length of the data received
670 *
671 * This function provides TDLS capabilities
672 *
673 * Return: 0 on success and errno on failure
674 */
675static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
676 struct wireless_dev *wdev,
677 const void *data,
678 int data_len)
679{
680 int status;
681 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
682 struct sk_buff *skb;
683 uint32_t set = 0;
684
Jeff Johnson1f61b612016-02-12 16:28:33 -0800685 ENTER_DEV(wdev->netdev);
686
Anurag Chouhan6d760662016-02-20 16:05:43 +0530687 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 hdd_err("Command not allowed in FTM mode");
689 return -EPERM;
690 }
691
692 status = wlan_hdd_validate_context(hdd_ctx);
693 if (status)
694 return status;
695
696 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
697 NLMSG_HDRLEN);
698 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700699 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 goto fail;
701 }
702
703 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800704 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
706 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 goto fail;
709 }
710 } else {
711 set = set | WIFI_TDLS_SUPPORT;
712 set = set | (hdd_ctx->config->fTDLSExternalControl ?
713 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
714 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
715 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800716 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
718 hdd_ctx->max_num_tdls_sta) ||
719 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
720 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700721 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 goto fail;
723 }
724 }
725 return cfg80211_vendor_cmd_reply(skb);
726fail:
727 if (skb)
728 kfree_skb(skb);
729 return -EINVAL;
730}
731
732/**
733 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
734 * @wiphy: WIPHY structure pointer
735 * @wdev: Wireless device structure pointer
736 * @data: Pointer to the data received
737 * @data_len: Length of the data received
738 *
739 * This function provides TDLS capabilities
740 *
741 * Return: 0 on success and errno on failure
742 */
743static int
744wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
745 struct wireless_dev *wdev,
746 const void *data,
747 int data_len)
748{
749 int ret;
750
751 cds_ssr_protect(__func__);
752 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
753 data, data_len);
754 cds_ssr_unprotect(__func__);
755
756 return ret;
757}
758#endif
759
760#ifdef QCA_HT_2040_COEX
761static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
762#endif
763
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530764int wlan_hdd_merge_avoid_freqs(tHddAvoidFreqList *destFreqList,
765 tHddAvoidFreqList *srcFreqList)
766{
767 int i;
768 tHddAvoidFreqRange *avoidRange =
769 &destFreqList->avoidFreqRange[destFreqList->avoidFreqRangeCount];
770
771 destFreqList->avoidFreqRangeCount += srcFreqList->avoidFreqRangeCount;
772 if (destFreqList->avoidFreqRangeCount > HDD_MAX_AVOID_FREQ_RANGES) {
773 hdd_err("avoid freq overflow");
774 return -EINVAL;
775 }
776
777 for (i = 0; i < srcFreqList->avoidFreqRangeCount; i++) {
778 avoidRange->startFreq =
779 srcFreqList->avoidFreqRange[i].startFreq;
780 avoidRange->endFreq = srcFreqList->avoidFreqRange[i].endFreq;
781 avoidRange++;
782 }
783 return 0;
784}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785/*
786 * FUNCTION: wlan_hdd_send_avoid_freq_event
787 * This is called when wlan driver needs to send vendor specific
788 * avoid frequency range event to userspace
789 */
790int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
791 tHddAvoidFreqList *pAvoidFreqList)
792{
793 struct sk_buff *vendor_event;
794
795 ENTER();
796
797 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700798 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 return -EINVAL;
800 }
801
802 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700803 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 return -EINVAL;
805 }
806
807 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
808 NULL,
809 sizeof(tHddAvoidFreqList),
810 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
811 GFP_KERNEL);
812 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700813 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 return -EINVAL;
815 }
816
817 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
818 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
819
820 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
821
822 EXIT();
823 return 0;
824}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530826/**
827 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
828 * with respect to the channel passed.
829 * @chan: Channel
830 * @upper: If "true" then next channel is returned or else
831 * previous channel is returned.
832 *
833 * This function returns the next/previous adjacent-channel to
834 * the channel passed. If "upper = true" then next channel is
835 * returned else previous is returned.
836 */
837int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
838{
839 enum channel_enum ch_idx = reg_get_chan_enum(chan);
840
841 if (ch_idx == INVALID_CHANNEL)
842 return -EINVAL;
843
844 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
845 ch_idx++;
846 else if (!upper && (ch_idx > CHAN_ENUM_1))
847 ch_idx--;
848 else
849 return -EINVAL;
850
851 return WLAN_REG_CH_NUM(ch_idx);
852}
853
854/**
855 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
856 * avoided when Do_Not_Break_Stream is active.
857 * @pHddCtx: HDD Context
858 * @op_chan: AP/P2P-GO operating channel
859 *
860 * This function sends list of frequencies to be avoided when
861 * Do_Not_Break_Stream is active.
862 * To clear the avoid_frequency_list in the application,
863 * op_chan = 0 can be passed.
864 *
865 * Return: 0 on success and errno on failure
866 */
867int wlan_hdd_send_avoid_freq_for_dnbs(hdd_context_t *pHddCtx, uint8_t op_chan)
868{
869 tHddAvoidFreqList p2p_avoid_freq_list;
870 uint8_t min_chan, max_chan;
871 int ret;
872 int chan;
873
874 ENTER();
875
876 if (!pHddCtx) {
877 hdd_err("invalid param");
878 return -EINVAL;
879 }
880
881 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(tHddAvoidFreqList));
882 /*
883 * If channel passed is zero, clear the avoid_freq list in application.
884 */
885 if (!op_chan) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530886#ifdef FEATURE_WLAN_CH_AVOID
887 mutex_lock(&pHddCtx->avoid_freq_lock);
888 qdf_mem_zero(&pHddCtx->dnbs_avoid_freq_list,
889 sizeof(tHddAvoidFreqList));
890 if (pHddCtx->coex_avoid_freq_list.avoidFreqRangeCount)
891 memcpy(&p2p_avoid_freq_list,
892 &pHddCtx->coex_avoid_freq_list,
893 sizeof(tHddAvoidFreqList));
894 mutex_unlock(&pHddCtx->avoid_freq_lock);
895#endif
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530896 ret = wlan_hdd_send_avoid_freq_event(pHddCtx,
897 &p2p_avoid_freq_list);
898 if (ret)
899 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
900 ret);
901
902 return ret;
903 }
904
905 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
906 min_chan = REG_MIN_24GHZ_CH_NUM;
907 max_chan = REG_MAX_24GHZ_CH_NUM;
908 } else if WLAN_REG_IS_5GHZ_CH(op_chan) {
909 min_chan = REG_MIN_5GHZ_CH_NUM;
910 max_chan = REG_MAX_5GHZ_CH_NUM;
911 } else {
912 hdd_err("invalid channel:%d", op_chan);
913 return -EINVAL;
914 }
915
916 if ((op_chan > min_chan) && (op_chan < max_chan)) {
917 p2p_avoid_freq_list.avoidFreqRangeCount = 2;
918 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
919 wlan_chan_to_freq(min_chan);
920
921 /* Get channel before the op_chan */
922 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
923 if (chan < 0)
924 return -EINVAL;
925 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
926 wlan_chan_to_freq(chan);
927
928 /* Get channel next to the op_chan */
929 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
930 if (chan < 0)
931 return -EINVAL;
932 p2p_avoid_freq_list.avoidFreqRange[1].startFreq =
933 wlan_chan_to_freq(chan);
934
935 p2p_avoid_freq_list.avoidFreqRange[1].endFreq =
936 wlan_chan_to_freq(max_chan);
937 } else if (op_chan == min_chan) {
938 p2p_avoid_freq_list.avoidFreqRangeCount = 1;
939
940 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
941 if (chan < 0)
942 return -EINVAL;
943 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
944 wlan_chan_to_freq(chan);
945
946 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
947 wlan_chan_to_freq(max_chan);
948 } else {
949 p2p_avoid_freq_list.avoidFreqRangeCount = 1;
950 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
951 wlan_chan_to_freq(min_chan);
952
953 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
954 if (chan < 0)
955 return -EINVAL;
956 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
957 wlan_chan_to_freq(chan);
958 }
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530959#ifdef FEATURE_WLAN_CH_AVOID
960 mutex_lock(&pHddCtx->avoid_freq_lock);
961 pHddCtx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
962 if (pHddCtx->coex_avoid_freq_list.avoidFreqRangeCount) {
963 ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
964 &pHddCtx->coex_avoid_freq_list);
965 if (ret) {
966 mutex_unlock(&pHddCtx->avoid_freq_lock);
967 hdd_err("avoid freq merge failed");
968 return ret;
969 }
970 }
971 mutex_unlock(&pHddCtx->avoid_freq_lock);
972#endif
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530973 ret = wlan_hdd_send_avoid_freq_event(pHddCtx, &p2p_avoid_freq_list);
974 if (ret)
975 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
976
977 return ret;
978}
979
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800980/* vendor specific events */
981static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
987 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988
989#ifdef WLAN_FEATURE_NAN
990 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
991 .vendor_id =
992 QCA_NL80211_VENDOR_ID,
993 .subcmd =
994 QCA_NL80211_VENDOR_SUBCMD_NAN
995 },
996#endif
997
998#ifdef WLAN_FEATURE_STATS_EXT
999 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1000 .vendor_id =
1001 QCA_NL80211_VENDOR_ID,
1002 .subcmd =
1003 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1004 },
1005#endif /* WLAN_FEATURE_STATS_EXT */
1006#ifdef FEATURE_WLAN_EXTSCAN
1007 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1020 .
1021 vendor_id
1022 =
1023 QCA_NL80211_VENDOR_ID,
1024 .subcmd =
1025 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1026 },
1027 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1028 .
1029 vendor_id
1030 =
1031 QCA_NL80211_VENDOR_ID,
1032 .
1033 subcmd =
1034 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1037 .
1038 vendor_id
1039 =
1040 QCA_NL80211_VENDOR_ID,
1041 .
1042 subcmd
1043 =
1044 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1045 },
1046 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1047 .
1048 vendor_id
1049 =
1050 QCA_NL80211_VENDOR_ID,
1051 .subcmd =
1052 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1053 },
1054 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1055 .vendor_id =
1056 QCA_NL80211_VENDOR_ID,
1057 .subcmd =
1058 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1059 },
1060 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1061 .
1062 vendor_id
1063 =
1064 QCA_NL80211_VENDOR_ID,
1065 .subcmd =
1066 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1067 },
1068 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1069 .
1070 vendor_id
1071 =
1072 QCA_NL80211_VENDOR_ID,
1073 .subcmd =
1074 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1075 },
1076 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1077 .
1078 vendor_id
1079 =
1080 QCA_NL80211_VENDOR_ID,
1081 .
1082 subcmd
1083 =
1084 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1085 },
1086 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1087 .
1088 vendor_id
1089 =
1090 QCA_NL80211_VENDOR_ID,
1091 .
1092 subcmd =
1093 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1094 },
1095 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1096 .
1097 vendor_id
1098 =
1099 QCA_NL80211_VENDOR_ID,
1100 .
1101 subcmd
1102 =
1103 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1104 },
1105 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1106 .
1107 vendor_id
1108 =
1109 QCA_NL80211_VENDOR_ID,
1110 .
1111 subcmd
1112 =
1113 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1114 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001115#endif /* FEATURE_WLAN_EXTSCAN */
1116
1117#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1118 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1119 .vendor_id =
1120 QCA_NL80211_VENDOR_ID,
1121 .subcmd =
1122 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1123 },
1124 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1125 .vendor_id =
1126 QCA_NL80211_VENDOR_ID,
1127 .subcmd =
1128 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1129 },
1130 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1131 .vendor_id =
1132 QCA_NL80211_VENDOR_ID,
1133 .subcmd =
1134 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1135 },
1136 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1137 .vendor_id =
1138 QCA_NL80211_VENDOR_ID,
1139 .subcmd =
1140 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1141 },
1142 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1143 .vendor_id =
1144 QCA_NL80211_VENDOR_ID,
1145 .subcmd =
1146 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1147 },
1148 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1149 .vendor_id =
1150 QCA_NL80211_VENDOR_ID,
1151 .subcmd =
1152 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1153 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001154 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1155 .vendor_id =
1156 QCA_NL80211_VENDOR_ID,
1157 .subcmd =
1158 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1159 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1161 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1162 .vendor_id =
1163 QCA_NL80211_VENDOR_ID,
1164 .subcmd =
1165 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1166 },
1167 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1168 .vendor_id = QCA_NL80211_VENDOR_ID,
1169 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1170 },
1171#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1172 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1173 .vendor_id =
1174 QCA_NL80211_VENDOR_ID,
1175 .subcmd =
1176 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1177 },
1178#endif
1179 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1180 .vendor_id =
1181 QCA_NL80211_VENDOR_ID,
1182 .subcmd =
1183 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1184 },
1185 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1186 .vendor_id =
1187 QCA_NL80211_VENDOR_ID,
1188 .subcmd =
1189 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1190 },
1191 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1192 .vendor_id =
1193 QCA_NL80211_VENDOR_ID,
1194 .subcmd =
1195 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1196 },
1197 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1198 .vendor_id =
1199 QCA_NL80211_VENDOR_ID,
1200 .subcmd =
1201 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1202 },
1203 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1204 .vendor_id =
1205 QCA_NL80211_VENDOR_ID,
1206 .subcmd =
1207 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1208 },
1209#ifdef FEATURE_WLAN_EXTSCAN
1210 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1211 .vendor_id = QCA_NL80211_VENDOR_ID,
1212 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1213 },
1214 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1215 .vendor_id = QCA_NL80211_VENDOR_ID,
1216 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1217 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1219 .vendor_id = QCA_NL80211_VENDOR_ID,
1220 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1221 },
1222#endif /* FEATURE_WLAN_EXTSCAN */
1223 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1224 .vendor_id = QCA_NL80211_VENDOR_ID,
1225 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1226 },
1227#ifdef WLAN_FEATURE_MEMDUMP
1228 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1229 .vendor_id = QCA_NL80211_VENDOR_ID,
1230 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1231 },
1232#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001233#ifdef WLAN_FEATURE_TSF
1234 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1235 .vendor_id = QCA_NL80211_VENDOR_ID,
1236 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1237 },
1238#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1240 .vendor_id = QCA_NL80211_VENDOR_ID,
1241 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1242 },
1243 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1244 .vendor_id = QCA_NL80211_VENDOR_ID,
1245 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1246 },
1247 /* OCB events */
1248 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1249 .vendor_id = QCA_NL80211_VENDOR_ID,
1250 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1251 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001252#ifdef FEATURE_LFR_SUBNET_DETECTION
1253 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1254 .vendor_id = QCA_NL80211_VENDOR_ID,
1255 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1256 },
1257#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001258
1259#ifdef WLAN_FEATURE_NAN_DATAPATH
1260 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1261 .vendor_id = QCA_NL80211_VENDOR_ID,
1262 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1263 },
1264#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001265
1266 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1267 .vendor_id = QCA_NL80211_VENDOR_ID,
1268 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1269 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301270 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1271 .vendor_id = QCA_NL80211_VENDOR_ID,
1272 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1273 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301274 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1275 .vendor_id = QCA_NL80211_VENDOR_ID,
1276 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1277 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001278#ifdef WLAN_UMAC_CONVERGENCE
1279 COMMON_VENDOR_EVENTS
1280#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001281};
1282
1283/**
1284 * __is_driver_dfs_capable() - get driver DFS capability
1285 * @wiphy: pointer to wireless wiphy structure.
1286 * @wdev: pointer to wireless_dev structure.
1287 * @data: Pointer to the data to be passed via vendor interface
1288 * @data_len:Length of the data to be passed
1289 *
1290 * This function is called by userspace to indicate whether or not
1291 * the driver supports DFS offload.
1292 *
1293 * Return: 0 on success, negative errno on failure
1294 */
1295static int __is_driver_dfs_capable(struct wiphy *wiphy,
1296 struct wireless_dev *wdev,
1297 const void *data,
1298 int data_len)
1299{
1300 u32 dfs_capability = 0;
1301 struct sk_buff *temp_skbuff;
1302 int ret_val;
1303 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1304
Jeff Johnson1f61b612016-02-12 16:28:33 -08001305 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001306
1307 ret_val = wlan_hdd_validate_context(hdd_ctx);
1308 if (ret_val)
1309 return ret_val;
1310
Anurag Chouhan6d760662016-02-20 16:05:43 +05301311 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001312 hdd_err("Command not allowed in FTM mode");
1313 return -EPERM;
1314 }
1315
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001316 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001317
1318 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1319 NLMSG_HDRLEN);
1320
1321 if (temp_skbuff != NULL) {
1322 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1323 dfs_capability);
1324 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001325 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 kfree_skb(temp_skbuff);
1327
1328 return ret_val;
1329 }
1330
1331 return cfg80211_vendor_cmd_reply(temp_skbuff);
1332 }
1333
Jeff Johnson020db452016-06-29 14:37:26 -07001334 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001335 return -ENOMEM;
1336}
1337
1338/**
1339 * is_driver_dfs_capable() - get driver DFS capability
1340 * @wiphy: pointer to wireless wiphy structure.
1341 * @wdev: pointer to wireless_dev structure.
1342 * @data: Pointer to the data to be passed via vendor interface
1343 * @data_len:Length of the data to be passed
1344 *
1345 * This function is called by userspace to indicate whether or not
1346 * the driver supports DFS offload. This is an SSR-protected
1347 * wrapper function.
1348 *
1349 * Return: 0 on success, negative errno on failure
1350 */
1351static int is_driver_dfs_capable(struct wiphy *wiphy,
1352 struct wireless_dev *wdev,
1353 const void *data,
1354 int data_len)
1355{
1356 int ret;
1357
1358 cds_ssr_protect(__func__);
1359 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1360 cds_ssr_unprotect(__func__);
1361
1362 return ret;
1363}
1364
1365/**
1366 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1367 *
1368 * @adapter: SAP adapter pointer
1369 *
1370 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1371 * radio. So in case of DFS MCC scenario override current SAP given config
1372 * to follow concurrent SAP DFS config
1373 *
1374 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1375 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1377{
1378 hdd_adapter_t *con_sap_adapter;
1379 tsap_Config_t *sap_config, *con_sap_config;
1380 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001381 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001383 if (!hdd_ctx) {
1384 hdd_err("hdd context is NULL");
1385 return 0;
1386 }
1387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 /*
1389 * Check if AP+AP case, once primary AP chooses a DFS
1390 * channel secondary AP should always follow primary APs channel
1391 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001392 if (!policy_mgr_concurrent_beaconing_sessions_running(
1393 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 return 0;
1395
1396 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1397 if (!con_sap_adapter)
1398 return 0;
1399
1400 sap_config = &adapter->sessionCtx.ap.sapConfig;
1401 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1402 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1403
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001404 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001405 return 0;
1406
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001407 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001408 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001409 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001410 sap_config->channel = con_ch;
1411
1412 if (con_sap_config->acs_cfg.acs_mode == true) {
1413 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1414 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001415 hdd_err("Primary AP channel config error");
1416 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417 con_ch, con_sap_config->acs_cfg.pri_ch,
1418 con_sap_config->acs_cfg.ht_sec_ch);
1419 return -EINVAL;
1420 }
1421 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1422 * MCC restriction. So free ch list allocated in do_acs
1423 * func for Sec AP and realloc for Pri AP ch list size
1424 */
1425 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301426 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001427
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301428 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001429 &con_sap_config->acs_cfg,
1430 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301431 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001432 sizeof(uint8_t) *
1433 con_sap_config->acs_cfg.ch_list_count);
1434 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001435 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001436 return -ENOMEM;
1437 }
1438
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301439 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440 con_sap_config->acs_cfg.ch_list,
1441 con_sap_config->acs_cfg.ch_list_count);
1442
1443 } else {
1444 sap_config->acs_cfg.pri_ch = con_ch;
1445 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1446 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1447 }
1448
1449 return con_ch;
1450}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001451
1452/**
1453 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1454 * @sap_cfg: pointer to SAP config struct
1455 *
1456 * This function sets the default ACS start and end channel for the given band
1457 * and also parses the given ACS channel list.
1458 *
1459 * Return: None
1460 */
1461
1462static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1463 bool vht_enabled)
1464{
1465 int i;
1466 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1467 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001468 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1469 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1471 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001472 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1473 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001474 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1475 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001476 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1477 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001478 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1479 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001480 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1481 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001482 }
1483
1484 if (ht_enabled)
1485 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1486
1487 if (vht_enabled)
1488 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1489
1490
1491 /* Parse ACS Chan list from hostapd */
1492 if (!sap_cfg->acs_cfg.ch_list)
1493 return;
1494
1495 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1496 sap_cfg->acs_cfg.end_ch =
1497 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1498 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301499 /* avoid channel as start channel */
1500 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1501 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1503 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1504 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1505 }
1506}
1507
1508
1509static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1510
1511/**
1512 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1513 * @adapter: pointer to SAP adapter struct
1514 *
1515 * This function starts the ACS procedure if there are no
1516 * constraints like MBSSID DFS restrictions.
1517 *
1518 * Return: Status of ACS Start procedure
1519 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301520int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001521{
1522
1523 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1524 tsap_Config_t *sap_config;
1525 tpWLAN_SAPEventCB acs_event_callback;
1526 int status;
1527
1528 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301529 if (hdd_ctx->acs_policy.acs_channel)
1530 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1531 else
1532 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533
1534 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001535 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001536 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001537
1538 if (status > 0) {
1539 /*notify hostapd about channel override */
1540 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1541 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1542 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001543 }
Jeff Johnson68755312017-02-10 11:46:55 -08001544
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1546 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001547 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001548 return -EINVAL;
1549 }
1550
1551 acs_event_callback = hdd_hostapd_sap_event_cb;
1552
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301553 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301554 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301555 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001557 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 acs_event_callback, sap_config, adapter->dev);
1559
1560
1561 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001562 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 return -EINVAL;
1564 }
bings394afdd2017-01-09 11:22:38 +08001565 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1566 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001567 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1568
1569 return 0;
1570}
1571
1572/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301573 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1574 * @ap_adapter: AP adapter
1575 * @nol: Non-occupancy list
1576 * @nol_len: Length of NOL
1577 *
1578 * Get the NOL for SAP
1579 *
1580 * Return: Zero on success, non-zero on failure
1581 */
1582static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1583 uint32_t *nol_len)
1584{
1585 QDF_STATUS ret;
1586
1587 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1588 nol, nol_len);
1589 if (QDF_IS_STATUS_ERROR(ret))
1590 return -EINVAL;
1591
1592 return 0;
1593}
1594
1595/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301596 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1597 * @hdd_ctx: hdd context
1598 * @acs_chan_params: external acs channel params
1599 * @sap_config: SAP config
1600 *
1601 * This API provides unsorted pcl list.
1602 * this list is a subset of the valid channel list given by hostapd.
1603 * if channel is not present in pcl, weightage will be given as zero
1604 *
1605 * Return: Zero on success, non-zero on failure
1606 */
1607static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1608 struct hdd_vendor_acs_chan_params *acs_chan_params,
1609 tsap_Config_t *sap_config)
1610{
1611 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301612 /*
1613 * PCL shall contain only the preferred channels from the
1614 * application. If those channels are not present in the
1615 * driver PCL, then set the weight to zero
1616 */
1617 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1618 acs_chan_params->vendor_pcl_list[i] =
1619 sap_config->acs_cfg.ch_list[i];
1620 acs_chan_params->vendor_weight_list[i] = 0;
1621 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1622 if (sap_config->acs_cfg.ch_list[i] ==
1623 sap_config->acs_cfg.pcl_channels[j]) {
1624 acs_chan_params->vendor_weight_list[i] =
1625 sap_config->
1626 acs_cfg.pcl_channels_weight_list[j];
1627 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301628 }
1629 }
1630 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301631 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301632}
1633
1634/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301635 * hdd_update_reg_chan_info : This API contructs channel info
1636 * for all the given channel
1637 * @adapter: pointer to SAP adapter struct
1638 * @channel_count: channel count
1639 * @channel_list: channel list
1640 *
1641 * Return: Status of of channel information updation
1642 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301643static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301644 uint32_t channel_count,
1645 uint8_t *channel_list)
1646{
1647 int i;
1648 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001649 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301650 uint8_t bw_offset = 0, chan = 0;
1651 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1652 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1653
1654 /* memory allocation */
1655 sap_config->channel_info = qdf_mem_malloc(
1656 sizeof(struct hdd_channel_info) *
1657 channel_count);
1658 if (!sap_config->channel_info) {
1659 hdd_err("memory allocation failed");
1660 return -ENOMEM;
1661
1662 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301663 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301664 for (i = 0; i < channel_count; i++) {
1665 icv = &sap_config->channel_info[i];
1666 chan = channel_list[i];
1667
1668 if (chan == 0)
1669 continue;
1670
1671 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1672 bw_offset = 1 << BW_40_OFFSET_BIT;
1673 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1674 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001675 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301676 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001677 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1678 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301679
1680 /* filling demo values */
1681 icv->max_radio_power = HDD_MAX_TX_POWER;
1682 icv->min_radio_power = HDD_MIN_TX_POWER;
1683 /* not supported in current driver */
1684 icv->max_antenna_gain = 0;
1685
1686 icv->reg_class_id = wlan_hdd_find_opclass(
1687 WLAN_HDD_GET_HAL_CTX(adapter),
1688 chan, bw_offset);
1689
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001690 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301691 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001692 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1693 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301694 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1695 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1696 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001697
Kapil Gupta086c6202016-12-11 18:17:06 +05301698 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001699 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301700 sap_config->acs_cfg.ch_width,
1701 sap_config->acs_cfg.is_ht_enabled,
1702 sap_config->acs_cfg.is_vht_enabled,
1703 hdd_ctx->config->enable_sub_20_channel_width);
1704
1705 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1706 icv->freq, icv->flags,
1707 icv->flagext, icv->ieee_chan_number,
1708 icv->max_reg_power, icv->max_radio_power,
1709 icv->min_radio_power, icv->reg_class_id,
1710 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1711 icv->vht_center_freq_seg1);
1712 }
1713 return 0;
1714}
1715
1716/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1717#define CHAN_INFO_ATTR_FLAGS \
1718 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1719#define CHAN_INFO_ATTR_FLAG_EXT \
1720 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1721#define CHAN_INFO_ATTR_FREQ \
1722 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1723#define CHAN_INFO_ATTR_MAX_REG_POWER \
1724 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1725#define CHAN_INFO_ATTR_MAX_POWER \
1726 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1727#define CHAN_INFO_ATTR_MIN_POWER \
1728 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1729#define CHAN_INFO_ATTR_REG_CLASS_ID \
1730 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1731#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1732 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1733#define CHAN_INFO_ATTR_VHT_SEG_0 \
1734 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1735#define CHAN_INFO_ATTR_VHT_SEG_1 \
1736 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1737
1738/**
1739 * hdd_cfg80211_update_channel_info() - add channel info attributes
1740 * @skb: pointer to sk buff
1741 * @hdd_ctx: pointer to hdd station context
1742 * @idx: attribute index
1743 *
1744 * Return: Success(0) or reason code for failure
1745 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301746static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301747hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1748 tsap_Config_t *sap_config, int idx)
1749{
1750 struct nlattr *nla_attr, *channel;
1751 struct hdd_channel_info *icv;
1752 int i;
1753
1754 nla_attr = nla_nest_start(skb, idx);
1755 if (!nla_attr)
1756 goto fail;
1757
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301758 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301759 channel = nla_nest_start(skb, i);
1760 if (!channel)
1761 goto fail;
1762
1763 icv = &sap_config->channel_info[i];
1764 if (!icv) {
1765 hdd_err("channel info not found");
1766 goto fail;
1767 }
1768 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1769 icv->freq) ||
1770 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1771 icv->flags) ||
1772 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1773 icv->flagext) ||
1774 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1775 icv->max_reg_power) ||
1776 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1777 icv->max_radio_power) ||
1778 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1779 icv->min_radio_power) ||
1780 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1781 icv->reg_class_id) ||
1782 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1783 icv->max_antenna_gain) ||
1784 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1785 icv->vht_center_freq_seg0) ||
1786 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1787 icv->vht_center_freq_seg1)) {
1788 hdd_err("put fail");
1789 goto fail;
1790 }
1791 nla_nest_end(skb, channel);
1792 }
1793 nla_nest_end(skb, nla_attr);
1794 return 0;
1795fail:
1796 hdd_err("nl channel update failed");
1797 return -EINVAL;
1798}
1799#undef CHAN_INFO_ATTR_FLAGS
1800#undef CHAN_INFO_ATTR_FLAG_EXT
1801#undef CHAN_INFO_ATTR_FREQ
1802#undef CHAN_INFO_ATTR_MAX_REG_POWER
1803#undef CHAN_INFO_ATTR_MAX_POWER
1804#undef CHAN_INFO_ATTR_MIN_POWER
1805#undef CHAN_INFO_ATTR_REG_CLASS_ID
1806#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1807#undef CHAN_INFO_ATTR_VHT_SEG_0
1808#undef CHAN_INFO_ATTR_VHT_SEG_1
1809
1810/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301811 * hdd_cfg80211_update_pcl() - add pcl info attributes
1812 * @skb: pointer to sk buff
1813 * @hdd_ctx: pointer to hdd station context
1814 * @idx: attribute index
1815 * @vendor_pcl_list: PCL list
1816 * @vendor_weight_list: PCL weights
1817 *
1818 * Return: Success(0) or reason code for failure
1819 */
1820static int32_t
1821hdd_cfg80211_update_pcl(struct sk_buff *skb,
1822 uint8_t ch_list_count, int idx,
1823 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1824{
1825 struct nlattr *nla_attr, *channel;
1826 int i;
1827
1828 nla_attr = nla_nest_start(skb, idx);
1829
1830 if (!nla_attr)
1831 goto fail;
1832
1833 for (i = 0; i < ch_list_count; i++) {
1834 channel = nla_nest_start(skb, i);
1835 if (!channel)
1836 goto fail;
1837 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1838 vendor_pcl_list[i]) ||
1839 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1840 vendor_weight_list[i])) {
1841 hdd_err("put fail");
1842 goto fail;
1843 }
1844 nla_nest_end(skb, channel);
1845 }
1846 nla_nest_end(skb, nla_attr);
1847
1848 return 0;
1849fail:
1850 hdd_err("updating pcl list failed");
1851 return -EINVAL;
1852}
1853
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301854static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
1855 tsap_Config_t *sap_config,
1856 eCsrBand *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301857{
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301858 int i, temp_count = 0;
1859 int acs_list_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301860 /* Get scan band */
1861 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1862 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1863 *band = eCSR_BAND_24;
1864 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1865 *band = eCSR_BAND_5G;
1866 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1867 *band = eCSR_BAND_ALL;
1868 }
1869 /* Auto is not supported currently */
1870 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1871 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301872 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
1873 hdd_ctx->config->external_acs_freq_band)
1874 *band = eCSR_BAND_24;
1875 else
1876 *band = eCSR_BAND_5G;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301877 for (i = 0; i < acs_list_count; i++) {
1878 if (eCSR_BAND_24 == *band) {
1879 if (WLAN_REG_IS_24GHZ_CH(
1880 sap_config->acs_cfg.ch_list[i])) {
1881 sap_config->acs_cfg.ch_list[
1882 temp_count] =
1883 sap_config->acs_cfg.ch_list[i];
1884 temp_count++;
1885 }
1886 } else if (eCSR_BAND_5G == *band) {
1887 if (WLAN_REG_IS_5GHZ_CH(
1888 sap_config->acs_cfg.ch_list[i])) {
1889 sap_config->acs_cfg.ch_list[
1890 temp_count] =
1891 sap_config->acs_cfg.ch_list[i];
1892 temp_count++;
1893 }
1894 }
1895 }
1896 sap_config->acs_cfg.ch_list_count = temp_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301897 }
1898}
1899
1900void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1901 uint8_t reason)
1902{
1903 struct sk_buff *skb;
1904 tsap_Config_t *sap_config;
1905 uint32_t channel_count = 0, status;
1906 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1907 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1908 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1909 struct hdd_vendor_acs_chan_params acs_chan_params;
1910 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1911 eCsrBand band = eCSR_BAND_24;
1912 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301913 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
1914 uint32_t i;
1915
Kapil Gupta8878ad92017-02-13 11:56:04 +05301916
1917 if (!hdd_ctx) {
1918 hdd_err("HDD context is NULL");
1919 return;
1920 }
1921
1922 ENTER();
1923 sap_config = &adapter->sessionCtx.ap.sapConfig;
1924
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301925 hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301926 /* Get valid channels for SAP */
1927 wlan_hdd_sap_get_valid_channellist(adapter,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301928 &channel_count,
1929 channel_list,
1930 band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301931
1932 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301933 /* Get phymode */
1934 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1935
1936 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1937 &(adapter->wdev),
1938 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1939 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1940 GFP_KERNEL);
1941
1942 if (!skb) {
1943 hdd_err("cfg80211_vendor_event_alloc failed");
1944 return;
1945 }
1946 /*
1947 * Application expects pcl to be a subset of channel list
1948 * Remove all channels which are not in channel list from pcl
1949 * and add weight as zero
1950 */
1951 acs_chan_params.channel_count = channel_count;
1952 acs_chan_params.channel_list = channel_list;
1953 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1954 acs_chan_params.vendor_weight_list = vendor_weight_list;
1955
1956 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1957 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301958
1959 if (acs_chan_params.channel_count) {
1960 hdd_debug("ACS channel list: len: %d",
1961 acs_chan_params.channel_count);
1962 for (i = 0; i < acs_chan_params.channel_count; i++)
1963 hdd_debug("%d ", acs_chan_params.channel_list[i]);
1964 }
1965
1966 if (acs_chan_params.pcl_count) {
1967 hdd_debug("ACS PCL list: len: %d",
1968 acs_chan_params.pcl_count);
1969 for (i = 0; i < acs_chan_params.pcl_count; i++)
1970 hdd_debug("channel:%d, weight:%d ",
1971 acs_chan_params.
1972 vendor_pcl_list[i],
1973 acs_chan_params.
1974 vendor_weight_list[i]);
1975 }
1976
1977 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1978 hdd_ctx->config->external_acs_policy) {
1979 acs_policy =
1980 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
1981 } else {
1982 acs_policy =
1983 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
1984 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301985 /* Update values in NL buffer */
1986 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1987 reason) ||
1988 nla_put_u8(skb,
1989 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1990 false) ||
1991 nla_put_u8(skb,
1992 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1993 true) ||
1994 nla_put_u8(skb,
1995 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1996 true) ||
1997 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1998 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05301999 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
2000 band) ||
2001 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
2002 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05302003 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302004 channel_count, channel_list)) {
2005 hdd_err("nla put fail");
2006 goto fail;
2007 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302008 status =
2009 hdd_cfg80211_update_pcl(skb,
2010 acs_chan_params.
2011 pcl_count,
2012 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
2013 vendor_pcl_list,
2014 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302015
2016 if (status != 0)
2017 goto fail;
2018
2019 status = hdd_cfg80211_update_channel_info(skb, sap_config,
2020 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
2021
2022 if (status != 0)
2023 goto fail;
2024
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302025 status = nla_put_u32(skb,
2026 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
2027 acs_policy);
2028
2029 if (status != 0)
2030 goto fail;
2031
Kapil Gupta8878ad92017-02-13 11:56:04 +05302032 cfg80211_vendor_event(skb, GFP_KERNEL);
2033 return;
2034fail:
2035 if (skb)
2036 kfree_skb(skb);
2037}
2038
2039static int hdd_create_acs_timer(hdd_adapter_t *adapter)
2040{
2041 struct hdd_external_acs_timer_context *timer_context;
2042
2043 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
2044 return 0;
2045
2046 hdd_notice("Starting vendor app based ACS");
2047 timer_context = qdf_mem_malloc(sizeof(*timer_context));
2048 timer_context->adapter = adapter;
2049
2050 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
2051 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
2052 QDF_TIMER_TYPE_SW,
2053 hdd_acs_response_timeout_handler, timer_context);
2054 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
2055 return 0;
2056}
2057
2058/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002059 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2060 * @wiphy: Linux wiphy struct pointer
2061 * @wdev: Linux wireless device struct pointer
2062 * @data: ACS information from hostapd
2063 * @data_len: ACS information length
2064 *
2065 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2066 * and starts ACS procedure.
2067 *
2068 * Return: ACS procedure start status
2069 */
2070
2071static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2072 struct wireless_dev *wdev,
2073 const void *data, int data_len)
2074{
2075 struct net_device *ndev = wdev->netdev;
2076 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
2077 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2078 tsap_Config_t *sap_config;
2079 struct sk_buff *temp_skbuff;
2080 int status = -EINVAL, i = 0;
2081 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2082 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302083 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084
2085 /* ***Note*** Donot set SME config related to ACS operation here because
2086 * ACS operation is not synchronouse and ACS for Second AP may come when
2087 * ACS operation for first AP is going on. So only do_acs is split to
2088 * seperate start_acs routine. Also SME-PMAC struct that is used to
2089 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2090 * config shall be set only from start_acs.
2091 */
2092
2093 /* nla_policy Policy template. Policy not applied as some attributes are
2094 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
2095 *
2096 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2097 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2098 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2099 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2100 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2101 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
2102 */
2103
Jeff Johnson1f61b612016-02-12 16:28:33 -08002104 ENTER_DEV(ndev);
2105
Anurag Chouhan6d760662016-02-20 16:05:43 +05302106 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107 hdd_err("Command not allowed in FTM mode");
2108 return -EPERM;
2109 }
2110
Kapil Gupta8878ad92017-02-13 11:56:04 +05302111 if (hdd_ctx->config->force_sap_acs &&
2112 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07002113 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002114 return -EPERM;
2115 }
2116
2117 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302118 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302120
Naveen Rawat64e477e2016-05-20 10:34:56 -07002121 if (cds_is_sub_20_mhz_enabled()) {
2122 hdd_err("ACS not supported in sub 20 MHz ch wd.");
2123 status = -EINVAL;
2124 goto out;
2125 }
2126
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302128 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002129
2130 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
2131 NULL);
2132 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07002133 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002134 goto out;
2135 }
2136
2137 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002138 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139 goto out;
2140 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302141 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
2142 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143
2144 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2145 ht_enabled =
2146 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2147 else
2148 ht_enabled = 0;
2149
2150 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2151 ht40_enabled =
2152 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2153 else
2154 ht40_enabled = 0;
2155
2156 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2157 vht_enabled =
2158 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2159 else
2160 vht_enabled = 0;
2161
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302162 if (hdd_ctx->config->sap_force_11n_for_11ac) {
2163 vht_enabled = 0;
2164 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
2165 }
2166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002167 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2168 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2169 } else {
2170 if (ht_enabled && ht40_enabled)
2171 ch_width = 40;
2172 else
2173 ch_width = 20;
2174 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302175
2176 /* this may be possible, when sap_force_11n_for_11ac is set */
2177 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2178 if (ht_enabled && ht40_enabled)
2179 ch_width = 40;
2180 else
2181 ch_width = 20;
2182 }
2183
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 if (ch_width == 80)
2185 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2186 else if (ch_width == 40)
2187 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2188 else
2189 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2190
2191 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2192 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2193 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2194 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2195 * since it contains the frequency values of the channels in
2196 * the channel list.
2197 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2198 * is present
2199 */
2200 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2201 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2202 sap_config->acs_cfg.ch_list_count = nla_len(
2203 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2204 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302205 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002206 sizeof(uint8_t) *
2207 sap_config->acs_cfg.ch_list_count);
2208 if (sap_config->acs_cfg.ch_list == NULL)
2209 goto out;
2210
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302211 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 sap_config->acs_cfg.ch_list_count);
2213 }
2214 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2215 uint32_t *freq =
2216 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2217 sap_config->acs_cfg.ch_list_count = nla_len(
2218 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2219 sizeof(uint32_t);
2220 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302221 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002222 sap_config->acs_cfg.ch_list_count);
2223 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07002224 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225 status = -ENOMEM;
2226 goto out;
2227 }
2228
2229 /* convert frequency to channel */
2230 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2231 sap_config->acs_cfg.ch_list[i] =
2232 ieee80211_frequency_to_channel(freq[i]);
2233 }
2234 }
2235
2236 hdd_debug("get pcl for DO_ACS vendor command");
2237
2238 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002239 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302240 sap_config->acs_cfg.pcl_channels,
2241 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302242 sap_config->acs_cfg.pcl_channels_weight_list,
2243 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302244 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002245 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302247 if (sap_config->acs_cfg.pcl_ch_count) {
2248 hdd_debug("ACS config PCL: len: %d",
2249 sap_config->acs_cfg.pcl_ch_count);
2250 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2251 hdd_debug("channel:%d, weight:%d ",
2252 sap_config->acs_cfg.
2253 pcl_channels[i],
2254 sap_config->acs_cfg.
2255 pcl_channels_weight_list[i]);
2256 }
2257
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002258 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302259 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2260 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002261 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262 vht_enabled = 1;
2263 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2264 sap_config->acs_cfg.ch_width =
2265 hdd_ctx->config->vhtChannelWidth;
2266 /* No VHT80 in 2.4G so perform ACS accordingly */
2267 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302268 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302270 ch_width = 40;
2271 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 }
2273
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302274 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2275
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002276 hdd_debug("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002277 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2278 ch_width, ht_enabled, vht_enabled,
2279 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2280
Kapil Gupta8878ad92017-02-13 11:56:04 +05302281 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2282 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002284 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002285 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 sap_config->acs_cfg.ch_list_count);
2287 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002288 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002289 }
2290 sap_config->acs_cfg.acs_mode = true;
2291 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002292 /* ***Note*** Completion variable usage is not allowed
2293 * here since ACS scan operation may take max 2.2 sec
2294 * for 5G band:
2295 * 9 Active channel X 40 ms active scan time +
2296 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2298 * for this long. So we split up the scanning part.
2299 */
2300 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002301 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 status = 0;
2303 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302304 /* Check if vendor specific acs is enabled */
2305 if (hdd_ctx->config->vendor_acs_support) {
2306 sap_config->acs_cfg.hw_mode = hw_mode;
2307 hdd_create_acs_timer(adapter);
2308 hdd_update_acs_timer_reason(adapter,
2309 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2310 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2311 wlan_sap_set_vendor_acs(
2312 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2313 true);
2314 else
2315 wlan_sap_set_vendor_acs(
2316 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2317 false);
2318
2319 } else
2320 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002321 }
2322
2323out:
2324 if (0 == status) {
2325 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2326 NLMSG_HDRLEN);
2327 if (temp_skbuff != NULL)
2328 return cfg80211_vendor_cmd_reply(temp_skbuff);
2329 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002330 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002331 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2332
2333 return status;
2334}
2335
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002336/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2338 * @wiphy: Linux wiphy struct pointer
2339 * @wdev: Linux wireless device struct pointer
2340 * @data: ACS information from hostapd
2341 * @data_len: ACS information len
2342 *
2343 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2344 * and starts ACS procedure.
2345 *
2346 * Return: ACS procedure start status
2347 */
2348
2349static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2350 struct wireless_dev *wdev,
2351 const void *data, int data_len)
2352{
2353 int ret;
2354
2355 cds_ssr_protect(__func__);
2356 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2357 cds_ssr_unprotect(__func__);
2358
2359 return ret;
2360}
2361
2362/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002363 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2364 * @adapter: Pointer to adapter struct
2365 *
2366 * This function handle cleanup of what was done in DO_ACS, including free
2367 * memory.
2368 *
2369 * Return: void
2370 */
2371
2372void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2373{
2374 if (adapter == NULL)
2375 return;
2376 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2377 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2378 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2379 }
2380}
2381
2382/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2384 * @work: Linux workqueue struct pointer for ACS work
2385 *
2386 * This function starts the ACS procedure which was marked pending when an ACS
2387 * procedure was in progress for a concurrent SAP interface.
2388 *
2389 * Return: None
2390 */
2391
2392static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2393{
2394 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2395 acs_pending_work.work);
2396 wlan_hdd_cfg80211_start_acs(adapter);
2397}
2398
2399/**
2400 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2401 * @adapter: Pointer to SAP adapter struct
2402 * @pri_channel: SAP ACS procedure selected Primary channel
2403 * @sec_channel: SAP ACS procedure selected secondary channel
2404 *
2405 * This is a callback function from SAP module on ACS procedure is completed.
2406 * This function send the ACS selected channel information to hostapd
2407 *
2408 * Return: None
2409 */
2410
2411void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2412{
2413 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2414 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2415 struct sk_buff *vendor_event;
2416 int ret_val;
2417 hdd_adapter_t *con_sap_adapter;
2418 uint16_t ch_width;
2419
2420 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002421 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002422 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2423 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2424 GFP_KERNEL);
2425
2426 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002427 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 return;
2429 }
2430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431 ret_val = nla_put_u8(vendor_event,
2432 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2433 sap_cfg->acs_cfg.pri_ch);
2434 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002435 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436 kfree_skb(vendor_event);
2437 return;
2438 }
2439
2440 ret_val = nla_put_u8(vendor_event,
2441 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2442 sap_cfg->acs_cfg.ht_sec_ch);
2443 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002444 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 kfree_skb(vendor_event);
2446 return;
2447 }
2448
2449 ret_val = nla_put_u8(vendor_event,
2450 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2451 sap_cfg->acs_cfg.vht_seg0_center_ch);
2452 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002453 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 kfree_skb(vendor_event);
2455 return;
2456 }
2457
2458 ret_val = nla_put_u8(vendor_event,
2459 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2460 sap_cfg->acs_cfg.vht_seg1_center_ch);
2461 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002462 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 kfree_skb(vendor_event);
2464 return;
2465 }
2466
2467 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2468 ch_width = 80;
2469 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2470 ch_width = 40;
2471 else
2472 ch_width = 20;
2473
2474 ret_val = nla_put_u16(vendor_event,
2475 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2476 ch_width);
2477 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002478 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 kfree_skb(vendor_event);
2480 return;
2481 }
2482 if (sap_cfg->acs_cfg.pri_ch > 14)
2483 ret_val = nla_put_u8(vendor_event,
2484 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2485 QCA_ACS_MODE_IEEE80211A);
2486 else
2487 ret_val = nla_put_u8(vendor_event,
2488 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2489 QCA_ACS_MODE_IEEE80211G);
2490
2491 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002492 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002493 kfree_skb(vendor_event);
2494 return;
2495 }
2496
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002497 hdd_debug("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002498 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2499 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2500 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2501
2502 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2503 /* ***Note*** As already mentioned Completion variable usage is not
2504 * allowed here since ACS scan operation may take max 2.2 sec.
2505 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2506 * operation.
2507 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2508 * when Primary AP ACS is complete and secondary AP ACS is started here
2509 * immediately, Primary AP start_bss may come inbetween ACS operation
2510 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2511 * delay. This path and below constraint will be removed on sessionizing
2512 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2513 * As per design constraint user space control application must take
2514 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2515 * this code path. Sec AP hostapd should be started after Primary AP
2516 * start beaconing which can be confirmed by getchannel iwpriv command
2517 */
2518
2519 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2520 if (con_sap_adapter &&
2521 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2523 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 /* Lets give 500ms for OBSS + START_BSS to complete */
2525 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2526 msecs_to_jiffies(500));
2527 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2528 }
2529
2530 return;
2531}
2532
2533static int
2534__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2535 struct wireless_dev *wdev,
2536 const void *data,
2537 int data_len)
2538{
2539 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2540 struct sk_buff *skb = NULL;
2541 uint32_t fset = 0;
2542 int ret;
2543
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002544 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302545
Anurag Chouhan6d760662016-02-20 16:05:43 +05302546 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 hdd_err("Command not allowed in FTM mode");
2548 return -EPERM;
2549 }
2550
2551 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302552 if (ret)
2553 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554
2555 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002556 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 fset |= WIFI_FEATURE_INFRA;
2558 }
2559 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002560 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 fset |= WIFI_FEATURE_INFRA_5G;
2562 }
2563#ifdef WLAN_FEATURE_P2P
2564 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2565 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002566 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567 fset |= WIFI_FEATURE_P2P;
2568 }
2569#endif
2570 fset |= WIFI_FEATURE_SOFT_AP;
2571
2572 /* HOTSPOT is a supplicant feature, enable it by default */
2573 fset |= WIFI_FEATURE_HOTSPOT;
2574
2575#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302576 if (pHddCtx->config->extscan_enabled &&
2577 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002578 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2580 }
2581#endif
2582 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002583 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584 fset |= WIFI_FEATURE_NAN;
2585 }
2586 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002587 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002588 fset |= WIFI_FEATURE_D2D_RTT;
2589 fset |= WIFI_FEATURE_D2AP_RTT;
2590 }
2591#ifdef FEATURE_WLAN_SCAN_PNO
2592 if (pHddCtx->config->configPNOScanSupport &&
2593 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002594 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 fset |= WIFI_FEATURE_PNO;
2596 }
2597#endif
2598 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2599#ifdef FEATURE_WLAN_TDLS
2600 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2601 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002602 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 fset |= WIFI_FEATURE_TDLS;
2604 }
2605 if (sme_is_feature_supported_by_fw(TDLS) &&
2606 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2607 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002608 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2610 }
2611#endif
2612#ifdef WLAN_AP_STA_CONCURRENCY
2613 fset |= WIFI_FEATURE_AP_STA;
2614#endif
2615 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002616 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002617
2618 if (hdd_link_layer_stats_supported())
2619 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2620
2621 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2622 NLMSG_HDRLEN);
2623 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002624 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 return -EINVAL;
2626 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002627 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002629 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630 goto nla_put_failure;
2631 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302632 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302633 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002634nla_put_failure:
2635 kfree_skb(skb);
2636 return -EINVAL;
2637}
2638
2639/**
2640 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2641 * @wiphy: pointer to wireless wiphy structure.
2642 * @wdev: pointer to wireless_dev structure.
2643 * @data: Pointer to the data to be passed via vendor interface
2644 * @data_len:Length of the data to be passed
2645 *
2646 * Return: Return the Success or Failure code.
2647 */
2648static int
2649wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2650 struct wireless_dev *wdev,
2651 const void *data, int data_len)
2652{
2653 int ret = 0;
2654
2655 cds_ssr_protect(__func__);
2656 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2657 data, data_len);
2658 cds_ssr_unprotect(__func__);
2659
2660 return ret;
2661}
2662
2663/**
2664 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2665 * @wiphy: pointer to wireless wiphy structure.
2666 * @wdev: pointer to wireless_dev structure.
2667 * @data: Pointer to the data to be passed via vendor interface
2668 * @data_len:Length of the data to be passed
2669 *
2670 * Set the MAC address that is to be used for scanning.
2671 *
2672 * Return: Return the Success or Failure code.
2673 */
2674static int
2675__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2676 struct wireless_dev *wdev,
2677 const void *data,
2678 int data_len)
2679{
2680 tpSirScanMacOui pReqMsg = NULL;
2681 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2682 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302683 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 int ret;
2685
Jeff Johnson1f61b612016-02-12 16:28:33 -08002686 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687
Anurag Chouhan6d760662016-02-20 16:05:43 +05302688 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 hdd_err("Command not allowed in FTM mode");
2690 return -EPERM;
2691 }
2692
2693 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302694 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696
2697 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002698 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699 return -ENOTSUPP;
2700 }
2701
2702 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2703 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002704 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 return -EINVAL;
2706 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302707 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002709 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 return -ENOMEM;
2711 }
2712 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002713 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 goto fail;
2715 }
2716 nla_memcpy(&pReqMsg->oui[0],
2717 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2718 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002719 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 pReqMsg->oui[1], pReqMsg->oui[2]);
2721 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302722 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002723 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724 goto fail;
2725 }
2726 return 0;
2727fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302728 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002729 return -EINVAL;
2730}
2731
2732/**
2733 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2734 * @wiphy: pointer to wireless wiphy structure.
2735 * @wdev: pointer to wireless_dev structure.
2736 * @data: Pointer to the data to be passed via vendor interface
2737 * @data_len:Length of the data to be passed
2738 *
2739 * Set the MAC address that is to be used for scanning. This is an
2740 * SSR-protecting wrapper function.
2741 *
2742 * Return: Return the Success or Failure code.
2743 */
2744static int
2745wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2746 struct wireless_dev *wdev,
2747 const void *data,
2748 int data_len)
2749{
2750 int ret;
2751
2752 cds_ssr_protect(__func__);
2753 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2754 data, data_len);
2755 cds_ssr_unprotect(__func__);
2756
2757 return ret;
2758}
2759
2760/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302761 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2762 * @wiphy: pointer phy adapter
2763 * @wdev: pointer to wireless device structure
2764 * @data: pointer to data buffer
2765 * @data_len: length of data
2766 *
2767 * This routine will give concurrency matrix
2768 *
2769 * Return: int status code
2770 */
2771static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2772 struct wireless_dev *wdev,
2773 const void *data,
2774 int data_len)
2775{
2776 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2777 uint8_t i, feature_sets, max_feature_sets;
2778 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2779 struct sk_buff *reply_skb;
2780 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2781 int ret;
2782
2783 ENTER_DEV(wdev->netdev);
2784
2785 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2786 hdd_err("Command not allowed in FTM mode");
2787 return -EPERM;
2788 }
2789
2790 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302791 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302792 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302793
2794 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2795 data, data_len, NULL)) {
2796 hdd_err("Invalid ATTR");
2797 return -EINVAL;
2798 }
2799
2800 /* Parse and fetch max feature set */
2801 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2802 hdd_err("Attr max feature set size failed");
2803 return -EINVAL;
2804 }
2805 max_feature_sets = nla_get_u32(tb[
2806 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002807 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302808
2809 /* Fill feature combination matrix */
2810 feature_sets = 0;
2811 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002812 WIFI_FEATURE_P2P;
2813 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2814 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302815 /* Add more feature combinations here */
2816
2817 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002818 hdd_debug("Number of feature sets: %d", feature_sets);
2819 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302820 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002821 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302822
2823 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2824 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2825 if (!reply_skb) {
2826 hdd_err("Feature set matrix: buffer alloc fail");
2827 return -ENOMEM;
2828 }
2829
2830 if (nla_put_u32(reply_skb,
2831 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2832 feature_sets) ||
2833 nla_put(reply_skb,
2834 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2835 sizeof(u32) * feature_sets,
2836 feature_set_matrix)) {
2837 hdd_err("nla put fail");
2838 kfree_skb(reply_skb);
2839 return -EINVAL;
2840 }
2841 return cfg80211_vendor_cmd_reply(reply_skb);
2842}
2843
2844/**
2845 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2846 * @wiphy: pointer to wireless wiphy structure.
2847 * @wdev: pointer to wireless_dev structure.
2848 * @data: Pointer to the data to be passed via vendor interface
2849 * @data_len:Length of the data to be passed
2850 *
2851 * Retrieves the concurrency feature set matrix
2852 *
2853 * Return: 0 on success, negative errno on failure
2854 */
2855static int
2856wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2857 struct wireless_dev *wdev,
2858 const void *data,
2859 int data_len)
2860{
2861 int ret;
2862
2863 cds_ssr_protect(__func__);
2864 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2865 data, data_len);
2866 cds_ssr_unprotect(__func__);
2867
2868 return ret;
2869}
2870
2871/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002872 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2873 * @feature_flags: pointer to the byte array of features.
2874 * @feature: Feature to be turned ON in the byte array.
2875 *
2876 * Return: None
2877 *
2878 * This is called to turn ON or SET the feature flag for the requested feature.
2879 **/
2880#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002881static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2882 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883{
2884 uint32_t index;
2885 uint8_t bit_mask;
2886
2887 index = feature / NUM_BITS_IN_BYTE;
2888 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2889 feature_flags[index] |= bit_mask;
2890}
2891
2892/**
2893 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2894 * @wiphy: pointer to wireless wiphy structure.
2895 * @wdev: pointer to wireless_dev structure.
2896 * @data: Pointer to the data to be passed via vendor interface
2897 * @data_len:Length of the data to be passed
2898 *
2899 * This is called when wlan driver needs to send supported feature set to
2900 * supplicant upon a request/query from the supplicant.
2901 *
2902 * Return: Return the Success or Failure code.
2903 **/
2904#define MAX_CONCURRENT_CHAN_ON_24G 2
2905#define MAX_CONCURRENT_CHAN_ON_5G 2
2906static int
2907__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2908 struct wireless_dev *wdev,
2909 const void *data, int data_len)
2910{
2911 struct sk_buff *skb = NULL;
2912 uint32_t dbs_capability = 0;
2913 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302914 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 int ret_val;
2916
2917 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2918 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2919
Jeff Johnson1f61b612016-02-12 16:28:33 -08002920 ENTER_DEV(wdev->netdev);
2921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2923 if (ret_val)
2924 return ret_val;
2925
Anurag Chouhan6d760662016-02-20 16:05:43 +05302926 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927 hdd_err("Command not allowed in FTM mode");
2928 return -EPERM;
2929 }
2930
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002931 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002932 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002933 wlan_hdd_cfg80211_set_feature(feature_flags,
2934 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2935 }
2936
2937 wlan_hdd_cfg80211_set_feature(feature_flags,
2938 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002939 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 wlan_hdd_cfg80211_set_feature(feature_flags,
2941 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002942
2943 if (wma_is_p2p_lo_capable())
2944 wlan_hdd_cfg80211_set_feature(feature_flags,
2945 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2946
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2948 NLMSG_HDRLEN);
2949
2950 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002951 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 return -ENOMEM;
2953 }
2954
2955 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2956 sizeof(feature_flags), feature_flags))
2957 goto nla_put_failure;
2958
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002959 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2960 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302961 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 if (one_by_one_dbs)
2963 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2964
2965 if (two_by_two_dbs)
2966 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2967
2968 if (!one_by_one_dbs && !two_by_two_dbs)
2969 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2970 } else {
2971 hdd_err("wma_get_dbs_hw_mode failed");
2972 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2973 }
2974
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002975 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976
2977 if (nla_put_u32(skb,
2978 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2979 MAX_CONCURRENT_CHAN_ON_24G))
2980 goto nla_put_failure;
2981
2982 if (nla_put_u32(skb,
2983 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2984 MAX_CONCURRENT_CHAN_ON_5G))
2985 goto nla_put_failure;
2986
2987 return cfg80211_vendor_cmd_reply(skb);
2988
2989nla_put_failure:
2990 kfree_skb(skb);
2991 return -EINVAL;
2992}
2993
2994/**
2995 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2996 * @wiphy: pointer to wireless wiphy structure.
2997 * @wdev: pointer to wireless_dev structure.
2998 * @data: Pointer to the data to be passed via vendor interface
2999 * @data_len:Length of the data to be passed
3000 *
3001 * This is called when wlan driver needs to send supported feature set to
3002 * supplicant upon a request/query from the supplicant.
3003 *
3004 * Return: Return the Success or Failure code.
3005 */
3006static int
3007wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3008 struct wireless_dev *wdev,
3009 const void *data, int data_len)
3010{
3011 int ret;
3012
3013 cds_ssr_protect(__func__);
3014 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
3015 data, data_len);
3016 cds_ssr_unprotect(__func__);
3017
3018 return ret;
3019}
3020
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303021#define PARAM_NUM_NW \
3022 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
3023#define PARAM_SET_BSSID \
3024 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
3025#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
3026#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027
3028/**
3029 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
3030 * @wiphy: The wiphy structure
3031 * @wdev: The wireless device
3032 * @data: Data passed by framework
3033 * @data_len: Parameters to be configured passed as data
3034 *
3035 * The roaming related parameters are configured by the framework
3036 * using this interface.
3037 *
3038 * Return: Return either success or failure code.
3039 */
3040static int
3041__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3042 struct wireless_dev *wdev, const void *data, int data_len)
3043{
3044 struct net_device *dev = wdev->netdev;
3045 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3046 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3047 uint8_t session_id;
3048 struct roam_ext_params roam_params;
3049 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303050 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
3052 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
3053 int rem, i;
3054 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08003055 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 int ret;
3057
Jeff Johnson1f61b612016-02-12 16:28:33 -08003058 ENTER_DEV(dev);
3059
Anurag Chouhan6d760662016-02-20 16:05:43 +05303060 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 hdd_err("Command not allowed in FTM mode");
3062 return -EPERM;
3063 }
3064
3065 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303066 if (ret)
3067 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003068
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05303069 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
3070 hdd_err("Driver Modules are closed");
3071 return -EINVAL;
3072 }
3073
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003074 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3075 data, data_len,
3076 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003077 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078 return -EINVAL;
3079 }
3080 /* Parse and fetch Command Type*/
3081 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003082 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 goto fail;
3084 }
3085 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303086 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
3088 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003089 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003090 goto fail;
3091 }
3092 req_id = nla_get_u32(
3093 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07003094 hdd_debug("Req Id (%d)", req_id);
3095 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003096 switch (cmd_type) {
3097 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
3098 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303099 if (tb[PARAM_NUM_NW]) {
3100 count = nla_get_u32(
3101 tb[PARAM_NUM_NW]);
3102 } else {
3103 hdd_err("Number of networks is not provided");
3104 goto fail;
3105 }
3106
3107 if (count &&
3108 tb[PRAM_SSID_LIST]) {
3109 nla_for_each_nested(curr_attr,
3110 tb[PRAM_SSID_LIST], rem) {
3111 if (nla_parse(tb2,
3112 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
3113 nla_data(curr_attr), nla_len(curr_attr),
3114 NULL)) {
3115 hdd_err("nla_parse failed");
3116 goto fail;
3117 }
3118 /* Parse and Fetch allowed SSID list*/
3119 if (!tb2[PARAM_LIST_SSID]) {
3120 hdd_err("attr allowed ssid failed");
3121 goto fail;
3122 }
3123 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
3124 /*
3125 * Upper Layers include a null termination
3126 * character. Check for the actual permissible
3127 * length of SSID and also ensure not to copy
3128 * the NULL termination character to the driver
3129 * buffer.
3130 */
3131 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
3132 ((buf_len - 1) <=
3133 SIR_MAC_MAX_SSID_LENGTH)) {
3134 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003135 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303136 tb2[PARAM_LIST_SSID], buf_len - 1);
3137 roam_params.ssid_allowed_list[i].length
3138 = buf_len - 1;
3139 hdd_debug("SSID[%d]: %.*s,length = %d",
3140 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 roam_params.ssid_allowed_list[i].length,
3142 roam_params.ssid_allowed_list[i].ssId,
3143 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303144 i++;
3145 } else {
3146 hdd_err("Invalid buffer length");
3147 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148 }
3149 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303150 if (i != count) {
3151 hdd_err("Invalid number of SSIDs i = %d, count = %d",
3152 i, count);
3153 goto fail;
3154 }
3155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07003157 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158 roam_params.num_ssid_allowed_list);
3159 sme_update_roam_params(pHddCtx->hHal, session_id,
3160 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3161 break;
3162 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3163 /* Parse and fetch 5G Boost Threshold */
3164 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003165 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 goto fail;
3167 }
3168 roam_params.raise_rssi_thresh_5g = nla_get_s32(
3169 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003170 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 roam_params.raise_rssi_thresh_5g);
3172 /* Parse and fetch 5G Penalty Threshold */
3173 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003174 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 goto fail;
3176 }
3177 roam_params.drop_rssi_thresh_5g = nla_get_s32(
3178 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003179 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 roam_params.drop_rssi_thresh_5g);
3181 /* Parse and fetch 5G Boost Factor */
3182 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003183 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003184 goto fail;
3185 }
3186 roam_params.raise_factor_5g = nla_get_u32(
3187 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003188 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003189 roam_params.raise_factor_5g);
3190 /* Parse and fetch 5G Penalty factor */
3191 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003192 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193 goto fail;
3194 }
3195 roam_params.drop_factor_5g = nla_get_u32(
3196 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003197 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 roam_params.drop_factor_5g);
3199 /* Parse and fetch 5G Max Boost */
3200 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003201 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 goto fail;
3203 }
3204 roam_params.max_raise_rssi_5g = nla_get_u32(
3205 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07003206 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 roam_params.max_raise_rssi_5g);
3208 /* Parse and fetch Rssi Diff */
3209 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003210 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 goto fail;
3212 }
3213 roam_params.rssi_diff = nla_get_s32(
3214 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07003215 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216 roam_params.rssi_diff);
3217 /* Parse and fetch Alert Rssi Threshold */
3218 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003219 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220 goto fail;
3221 }
3222 roam_params.alert_rssi_threshold = nla_get_u32(
3223 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003224 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 roam_params.alert_rssi_threshold);
3226 sme_update_roam_params(pHddCtx->hHal, session_id,
3227 roam_params,
3228 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3229 break;
3230 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3231 /* Parse and fetch Activate Good Rssi Roam */
3232 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003233 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 goto fail;
3235 }
3236 roam_params.good_rssi_roam = nla_get_s32(
3237 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07003238 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239 roam_params.good_rssi_roam);
3240 sme_update_roam_params(pHddCtx->hHal, session_id,
3241 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3242 break;
3243 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3244 /* Parse and fetch number of preferred BSSID */
3245 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003246 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 goto fail;
3248 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003249 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003251 if (count > MAX_BSSID_FAVORED) {
3252 hdd_err("Preferred BSSID count %u exceeds max %u",
3253 count, MAX_BSSID_FAVORED);
3254 goto fail;
3255 }
3256 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003257 i = 0;
3258 nla_for_each_nested(curr_attr,
3259 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3260 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003261
3262 if (i == count) {
3263 hdd_warn("Ignoring excess Preferred BSSID");
3264 break;
3265 }
3266
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 if (nla_parse(tb2,
3268 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3269 nla_data(curr_attr), nla_len(curr_attr),
3270 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003271 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 goto fail;
3273 }
3274 /* Parse and fetch MAC address */
3275 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003276 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277 goto fail;
3278 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003279 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303281 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003282 hdd_debug(MAC_ADDRESS_STR,
3283 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 /* Parse and fetch preference factor*/
3285 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003286 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003287 goto fail;
3288 }
3289 roam_params.bssid_favored_factor[i] = nla_get_u32(
3290 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003291 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003292 roam_params.bssid_favored_factor[i]);
3293 i++;
3294 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003295 if (i < count)
3296 hdd_warn("Num Preferred BSSID %u less than expected %u",
3297 i, count);
3298 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299 sme_update_roam_params(pHddCtx->hHal, session_id,
3300 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3301 break;
3302 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3303 /* Parse and fetch number of blacklist BSSID */
3304 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003305 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 goto fail;
3307 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003308 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003309 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003310 if (count > MAX_BSSID_AVOID_LIST) {
3311 hdd_err("Blacklist BSSID count %u exceeds max %u",
3312 count, MAX_BSSID_AVOID_LIST);
3313 goto fail;
3314 }
3315 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303317
3318 if (count &&
3319 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3320 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3322 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003323
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303324 if (i == count) {
3325 hdd_warn("Ignoring excess Blacklist BSSID");
3326 break;
3327 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003328
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303329 if (nla_parse(tb2,
3330 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3331 nla_data(curr_attr), nla_len(curr_attr),
3332 NULL)) {
3333 hdd_err("nla_parse failed");
3334 goto fail;
3335 }
3336 /* Parse and fetch MAC address */
3337 if (!tb2[PARAM_SET_BSSID]) {
3338 hdd_err("attr blacklist addr failed");
3339 goto fail;
3340 }
3341 nla_memcpy(
3342 roam_params.bssid_avoid_list[i].bytes,
3343 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3344 hdd_debug(MAC_ADDRESS_STR,
3345 MAC_ADDR_ARRAY(
3346 roam_params.bssid_avoid_list[i].bytes));
3347 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003348 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003350 if (i < count)
3351 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3352 i, count);
3353 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354 sme_update_roam_params(pHddCtx->hHal, session_id,
3355 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3356 break;
3357 }
3358 return 0;
3359fail:
3360 return -EINVAL;
3361}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303362#undef PARAM_NUM_NW
3363#undef PARAM_SET_BSSID
3364#undef PRAM_SSID_LIST
3365#undef PARAM_LIST_SSID
3366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003367
3368/**
3369 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3370 * @wiphy: pointer to wireless wiphy structure.
3371 * @wdev: pointer to wireless_dev structure.
3372 * @data: Pointer to the data to be passed via vendor interface
3373 * @data_len:Length of the data to be passed
3374 *
3375 * Return: Return the Success or Failure code.
3376 */
3377static int
3378wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3379 struct wireless_dev *wdev,
3380 const void *data,
3381 int data_len)
3382{
3383 int ret;
3384
3385 cds_ssr_protect(__func__);
3386 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3387 data, data_len);
3388 cds_ssr_unprotect(__func__);
3389
3390 return ret;
3391}
3392
3393static const struct nla_policy
3394wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3395 +1] = {
3396 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3397};
3398
3399/**
3400 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3401 * @hdd_ctx: HDD context
3402 * @device_mode: device mode
3403 * Return: bool
3404 */
3405static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003406 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407{
3408 hdd_adapter_t *adapter;
3409 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3410 hdd_ap_ctx_t *ap_ctx;
3411 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303412 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003413
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303414 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003416 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303417 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418 adapter = adapter_node->pAdapter;
3419
3420 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003421 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003422 ap_ctx =
3423 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3424
3425 /*
3426 * if there is SAP already running on DFS channel,
3427 * do not disable scan on dfs channels. Note that
3428 * with SAP on DFS, there cannot be conurrency on
3429 * single radio. But then we can have multiple
3430 * radios !!
3431 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003432 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3433 hdd_ctx->hdd_pdev,
3434 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003435 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003436 return true;
3437 }
3438 }
3439
3440 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003441 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442 sta_ctx =
3443 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3444
3445 /*
3446 * if STA is already connected on DFS channel,
3447 * do not disable scan on dfs channels
3448 */
3449 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003450 (CHANNEL_STATE_DFS ==
3451 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3452 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003453 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454 return true;
3455 }
3456 }
3457
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303458 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459 adapter_node,
3460 &next);
3461 adapter_node = next;
3462 }
3463
3464 return false;
3465}
3466
3467/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003468 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003469 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003470 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003471 *
3472 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003473 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003474 * Fails the disable request if any device is active on a DFS channel.
3475 *
3476 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003477 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003478
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003479int wlan_hdd_enable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3480 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303482 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003483 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003485 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
3486 hdd_info("DFS channels are already %s",
3487 enable_dfs_channels ? "enabled" : "disabled");
3488 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003490
3491 if (!enable_dfs_channels) {
3492 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3493 QDF_STA_MODE);
3494 if (err)
3495 return -EOPNOTSUPP;
3496
3497 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3498 QDF_SAP_MODE);
3499 if (err)
3500 return -EOPNOTSUPP;
3501 }
3502
3503 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
3504
3505 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3506
3507 /* pass dfs channel status to regulatory component */
3508 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
3509 enable_dfs_channels);
3510
3511 if (QDF_IS_STATUS_ERROR(status))
3512 hdd_err("Failed to %s DFS channels",
3513 enable_dfs_channels ? "enable" : "disable");
3514
3515 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003516}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003517
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003518/**
3519 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3520 * @wiphy: corestack handler
3521 * @wdev: wireless device
3522 * @data: data
3523 * @data_len: data length
3524 * Return: success(0) or reason code for failure
3525 */
3526static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3527 struct wireless_dev *wdev,
3528 const void *data,
3529 int data_len)
3530{
3531 struct net_device *dev = wdev->netdev;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003532 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3533 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3534 int ret_val;
3535 uint32_t no_dfs_flag = 0;
3536
Jeff Johnson1f61b612016-02-12 16:28:33 -08003537 ENTER_DEV(dev);
3538
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003539 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303540 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003541 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003542
3543 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3544 data, data_len,
3545 wlan_hdd_set_no_dfs_flag_config_policy)) {
3546 hdd_err("invalid attr");
3547 return -EINVAL;
3548 }
3549
3550 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3551 hdd_err("attr dfs flag failed");
3552 return -EINVAL;
3553 }
3554
3555 no_dfs_flag = nla_get_u32(
3556 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3557
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003558 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003559
3560 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003561 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003562 return -EINVAL;
3563 }
3564
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003565 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566 return ret_val;
3567}
3568
3569/**
3570 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3571 *
3572 * @wiphy: wiphy device pointer
3573 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003574 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003575 * @data_len: Buffer length
3576 *
3577 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3578 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3579 *
3580 * Return: EOK or other error codes.
3581 */
3582
3583static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3584 struct wireless_dev *wdev,
3585 const void *data,
3586 int data_len)
3587{
3588 int ret;
3589
3590 cds_ssr_protect(__func__);
3591 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3592 data, data_len);
3593 cds_ssr_unprotect(__func__);
3594
3595 return ret;
3596}
3597
Manikandan Mohan80dea792016-04-28 16:36:48 -07003598static const struct nla_policy
3599wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3600 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3601};
3602
3603/**
3604 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3605 * @wiphy: wiphy device pointer
3606 * @wdev: wireless device pointer
3607 * @data: Vendor command data buffer
3608 * @data_len: Buffer length
3609 *
3610 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3611 * setup WISA Mode features.
3612 *
3613 * Return: Success(0) or reason code for failure
3614 */
3615static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3616 struct wireless_dev *wdev, const void *data, int data_len)
3617{
3618 struct net_device *dev = wdev->netdev;
3619 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3620 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3621 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3622 struct sir_wisa_params wisa;
3623 int ret_val;
3624 QDF_STATUS status;
3625 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003626 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3627 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003628
3629 ENTER_DEV(dev);
3630 ret_val = wlan_hdd_validate_context(hdd_ctx);
3631 if (ret_val)
3632 goto err;
3633
3634 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3635 hdd_err("Command not allowed in FTM mode");
3636 return -EPERM;
3637 }
3638
3639 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3640 wlan_hdd_wisa_cmd_policy)) {
3641 hdd_err("Invalid WISA cmd attributes");
3642 ret_val = -EINVAL;
3643 goto err;
3644 }
3645 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3646 hdd_err("Invalid WISA mode");
3647 ret_val = -EINVAL;
3648 goto err;
3649 }
3650
3651 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003652 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003653 wisa.mode = wisa_mode;
3654 wisa.vdev_id = adapter->sessionId;
3655 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003656 if (!QDF_IS_STATUS_SUCCESS(status)) {
3657 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003658 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003659 }
3660 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003661 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003662 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3663 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003664 adapter->sessionId),
3665 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003666err:
3667 EXIT();
3668 return ret_val;
3669}
3670
3671/**
3672 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3673 * @wiphy: corestack handler
3674 * @wdev: wireless device
3675 * @data: data
3676 * @data_len: data length
3677 *
3678 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3679 * setup WISA mode features.
3680 *
3681 * Return: Success(0) or reason code for failure
3682 */
3683static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3684 struct wireless_dev *wdev,
3685 const void *data,
3686 int data_len)
3687{
3688 int ret;
3689
3690 cds_ssr_protect(__func__);
3691 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3692 cds_ssr_unprotect(__func__);
3693
3694 return ret;
3695}
3696
Anurag Chouhan96919482016-07-13 16:36:57 +05303697/*
3698 * define short names for the global vendor params
3699 * used by __wlan_hdd_cfg80211_get_station_cmd()
3700 */
3701#define STATION_INVALID \
3702 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3703#define STATION_INFO \
3704 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3705#define STATION_ASSOC_FAIL_REASON \
3706 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3707#define STATION_MAX \
3708 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3709
3710static const struct nla_policy
3711hdd_get_station_policy[STATION_MAX + 1] = {
3712 [STATION_INFO] = {.type = NLA_FLAG},
3713 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3714};
3715
3716/**
3717 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3718 * @hdd_ctx: HDD context within host driver
3719 * @wdev: wireless device
3720 *
3721 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3722 * Validate cmd attributes and send the station info to upper layers.
3723 *
3724 * Return: Success(0) or reason code for failure
3725 */
3726static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3727 hdd_adapter_t *adapter)
3728{
3729 struct sk_buff *skb = NULL;
3730 uint32_t nl_buf_len;
3731 hdd_station_ctx_t *hdd_sta_ctx;
3732
3733 nl_buf_len = NLMSG_HDRLEN;
3734 nl_buf_len += sizeof(uint32_t);
3735 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3736
3737 if (!skb) {
3738 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3739 return -ENOMEM;
3740 }
3741
3742 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3743
3744 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3745 hdd_sta_ctx->conn_info.assoc_status_code)) {
3746 hdd_err("put fail");
3747 goto fail;
3748 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303749
3750 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3751 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3752 hdd_sta_ctx->conn_info.cca)) {
3753 hdd_err("put fail");
3754 goto fail;
3755 }
3756
Anurag Chouhan96919482016-07-13 16:36:57 +05303757 return cfg80211_vendor_cmd_reply(skb);
3758fail:
3759 if (skb)
3760 kfree_skb(skb);
3761 return -EINVAL;
3762}
3763
3764/**
3765 * hdd_map_auth_type() - transform auth type specific to
3766 * vendor command
3767 * @auth_type: csr auth type
3768 *
3769 * Return: Success(0) or reason code for failure
3770 */
3771static int hdd_convert_auth_type(uint32_t auth_type)
3772{
3773 uint32_t ret_val;
3774
3775 switch (auth_type) {
3776 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3777 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3778 break;
3779 case eCSR_AUTH_TYPE_SHARED_KEY:
3780 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3781 break;
3782 case eCSR_AUTH_TYPE_WPA:
3783 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3784 break;
3785 case eCSR_AUTH_TYPE_WPA_PSK:
3786 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3787 break;
3788 case eCSR_AUTH_TYPE_AUTOSWITCH:
3789 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3790 break;
3791 case eCSR_AUTH_TYPE_WPA_NONE:
3792 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3793 break;
3794 case eCSR_AUTH_TYPE_RSN:
3795 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3796 break;
3797 case eCSR_AUTH_TYPE_RSN_PSK:
3798 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3799 break;
3800 case eCSR_AUTH_TYPE_FT_RSN:
3801 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3802 break;
3803 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3804 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3805 break;
3806 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3807 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3808 break;
3809 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3810 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3811 break;
3812 case eCSR_AUTH_TYPE_CCKM_WPA:
3813 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3814 break;
3815 case eCSR_AUTH_TYPE_CCKM_RSN:
3816 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3817 break;
3818 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3819 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3820 break;
3821 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3822 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3823 break;
3824 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3825 case eCSR_AUTH_TYPE_FAILED:
3826 case eCSR_AUTH_TYPE_NONE:
3827 default:
3828 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3829 break;
3830 }
3831 return ret_val;
3832}
3833
3834/**
3835 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3836 * vendor command
3837 * @dot11mode: dot11mode
3838 *
3839 * Return: Success(0) or reason code for failure
3840 */
3841static int hdd_convert_dot11mode(uint32_t dot11mode)
3842{
3843 uint32_t ret_val;
3844
3845 switch (dot11mode) {
3846 case eCSR_CFG_DOT11_MODE_11A:
3847 ret_val = QCA_WLAN_802_11_MODE_11A;
3848 break;
3849 case eCSR_CFG_DOT11_MODE_11B:
3850 ret_val = QCA_WLAN_802_11_MODE_11B;
3851 break;
3852 case eCSR_CFG_DOT11_MODE_11G:
3853 ret_val = QCA_WLAN_802_11_MODE_11G;
3854 break;
3855 case eCSR_CFG_DOT11_MODE_11N:
3856 ret_val = QCA_WLAN_802_11_MODE_11N;
3857 break;
3858 case eCSR_CFG_DOT11_MODE_11AC:
3859 ret_val = QCA_WLAN_802_11_MODE_11AC;
3860 break;
3861 case eCSR_CFG_DOT11_MODE_AUTO:
3862 case eCSR_CFG_DOT11_MODE_ABG:
3863 default:
3864 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3865 }
3866 return ret_val;
3867}
3868
3869/**
3870 * hdd_add_tx_bitrate() - add tx bitrate attribute
3871 * @skb: pointer to sk buff
3872 * @hdd_sta_ctx: pointer to hdd station context
3873 * @idx: attribute index
3874 *
3875 * Return: Success(0) or reason code for failure
3876 */
3877static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3878 hdd_station_ctx_t *hdd_sta_ctx,
3879 int idx)
3880{
3881 struct nlattr *nla_attr;
3882 uint32_t bitrate, bitrate_compat;
3883
3884 nla_attr = nla_nest_start(skb, idx);
3885 if (!nla_attr)
3886 goto fail;
3887 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3888 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3889
3890 /* report 16-bit bitrate only if we can */
3891 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3892 if (bitrate > 0 &&
3893 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3894 hdd_err("put fail");
3895 goto fail;
3896 }
3897 if (bitrate_compat > 0 &&
3898 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3899 hdd_err("put fail");
3900 goto fail;
3901 }
3902 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3903 hdd_sta_ctx->conn_info.txrate.nss)) {
3904 hdd_err("put fail");
3905 goto fail;
3906 }
3907 nla_nest_end(skb, nla_attr);
3908 return 0;
3909fail:
3910 return -EINVAL;
3911}
3912
3913/**
3914 * hdd_add_sta_info() - add station info attribute
3915 * @skb: pointer to sk buff
3916 * @hdd_sta_ctx: pointer to hdd station context
3917 * @idx: attribute index
3918 *
3919 * Return: Success(0) or reason code for failure
3920 */
3921static int32_t hdd_add_sta_info(struct sk_buff *skb,
3922 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3923{
3924 struct nlattr *nla_attr;
3925
3926 nla_attr = nla_nest_start(skb, idx);
3927 if (!nla_attr)
3928 goto fail;
3929 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3930 (hdd_sta_ctx->conn_info.signal + 100))) {
3931 hdd_err("put fail");
3932 goto fail;
3933 }
3934 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3935 goto fail;
3936 nla_nest_end(skb, nla_attr);
3937 return 0;
3938fail:
3939 return -EINVAL;
3940}
3941
3942/**
3943 * hdd_add_survey_info() - add survey info attribute
3944 * @skb: pointer to sk buff
3945 * @hdd_sta_ctx: pointer to hdd station context
3946 * @idx: attribute index
3947 *
3948 * Return: Success(0) or reason code for failure
3949 */
3950static int32_t hdd_add_survey_info(struct sk_buff *skb,
3951 hdd_station_ctx_t *hdd_sta_ctx,
3952 int idx)
3953{
3954 struct nlattr *nla_attr;
3955
3956 nla_attr = nla_nest_start(skb, idx);
3957 if (!nla_attr)
3958 goto fail;
3959 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3960 hdd_sta_ctx->conn_info.freq) ||
3961 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3962 (hdd_sta_ctx->conn_info.noise + 100))) {
3963 hdd_err("put fail");
3964 goto fail;
3965 }
3966 nla_nest_end(skb, nla_attr);
3967 return 0;
3968fail:
3969 return -EINVAL;
3970}
3971
3972/**
3973 * hdd_add_link_standard_info() - add link info attribute
3974 * @skb: pointer to sk buff
3975 * @hdd_sta_ctx: pointer to hdd station context
3976 * @idx: attribute index
3977 *
3978 * Return: Success(0) or reason code for failure
3979 */
3980static int32_t
3981hdd_add_link_standard_info(struct sk_buff *skb,
3982 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3983{
3984 struct nlattr *nla_attr;
3985
3986 nla_attr = nla_nest_start(skb, idx);
3987 if (!nla_attr)
3988 goto fail;
3989 if (nla_put(skb,
3990 NL80211_ATTR_SSID,
3991 hdd_sta_ctx->conn_info.SSID.SSID.length,
3992 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3993 hdd_err("put fail");
3994 goto fail;
3995 }
3996 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3997 goto fail;
3998 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3999 goto fail;
4000 nla_nest_end(skb, nla_attr);
4001 return 0;
4002fail:
4003 return -EINVAL;
4004}
4005
4006/**
4007 * hdd_add_ap_standard_info() - add ap info attribute
4008 * @skb: pointer to sk buff
4009 * @hdd_sta_ctx: pointer to hdd station context
4010 * @idx: attribute index
4011 *
4012 * Return: Success(0) or reason code for failure
4013 */
4014static int32_t
4015hdd_add_ap_standard_info(struct sk_buff *skb,
4016 hdd_station_ctx_t *hdd_sta_ctx, int idx)
4017{
4018 struct nlattr *nla_attr;
4019
4020 nla_attr = nla_nest_start(skb, idx);
4021 if (!nla_attr)
4022 goto fail;
4023 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
4024 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
4025 sizeof(hdd_sta_ctx->conn_info.vht_caps),
4026 &hdd_sta_ctx->conn_info.vht_caps)) {
4027 hdd_err("put fail");
4028 goto fail;
4029 }
4030 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
4031 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
4032 sizeof(hdd_sta_ctx->conn_info.ht_caps),
4033 &hdd_sta_ctx->conn_info.ht_caps)) {
4034 hdd_err("put fail");
4035 goto fail;
4036 }
4037 nla_nest_end(skb, nla_attr);
4038 return 0;
4039fail:
4040 return -EINVAL;
4041}
4042
4043/**
4044 * hdd_get_station_info() - send BSS information to supplicant
4045 * @hdd_ctx: pointer to hdd context
4046 * @adapter: pointer to adapter
4047 *
4048 * Return: 0 if success else error status
4049 */
4050static int hdd_get_station_info(hdd_context_t *hdd_ctx,
4051 hdd_adapter_t *adapter)
4052{
4053 struct sk_buff *skb = NULL;
4054 uint8_t *tmp_hs20 = NULL;
4055 uint32_t nl_buf_len;
4056 hdd_station_ctx_t *hdd_sta_ctx;
4057
4058 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4059
4060 nl_buf_len = NLMSG_HDRLEN;
4061 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
4062 sizeof(hdd_sta_ctx->conn_info.freq) +
4063 sizeof(hdd_sta_ctx->conn_info.noise) +
4064 sizeof(hdd_sta_ctx->conn_info.signal) +
4065 (sizeof(uint32_t) * 2) +
4066 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
4067 sizeof(hdd_sta_ctx->conn_info.roam_count) +
4068 sizeof(hdd_sta_ctx->conn_info.authType) +
4069 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
4070 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
4071 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
4072 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
4073 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
4074 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
4075 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
4076 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
4077 1);
4078 }
4079 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
4080 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
4081 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
4082 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
4083
4084
4085 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
4086 if (!skb) {
4087 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
4088 return -ENOMEM;
4089 }
4090
4091 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
4092 LINK_INFO_STANDARD_NL80211_ATTR)) {
4093 hdd_err("put fail");
4094 goto fail;
4095 }
4096 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
4097 AP_INFO_STANDARD_NL80211_ATTR)) {
4098 hdd_err("put fail");
4099 goto fail;
4100 }
4101 if (nla_put_u32(skb, INFO_ROAM_COUNT,
4102 hdd_sta_ctx->conn_info.roam_count) ||
4103 nla_put_u32(skb, INFO_AKM,
4104 hdd_convert_auth_type(
4105 hdd_sta_ctx->conn_info.authType)) ||
4106 nla_put_u32(skb, WLAN802_11_MODE,
4107 hdd_convert_dot11mode(
4108 hdd_sta_ctx->conn_info.dot11Mode))) {
4109 hdd_err("put fail");
4110 goto fail;
4111 }
4112 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
4113 if (nla_put(skb, HT_OPERATION,
4114 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
4115 &hdd_sta_ctx->conn_info.ht_operation)) {
4116 hdd_err("put fail");
4117 goto fail;
4118 }
4119 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
4120 if (nla_put(skb, VHT_OPERATION,
4121 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
4122 &hdd_sta_ctx->conn_info.vht_operation)) {
4123 hdd_err("put fail");
4124 goto fail;
4125 }
4126 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
4127 if (nla_put(skb, AP_INFO_HS20_INDICATION,
4128 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
4129 tmp_hs20 + 1)) {
4130 hdd_err("put fail");
4131 goto fail;
4132 }
4133
4134 return cfg80211_vendor_cmd_reply(skb);
4135fail:
4136 if (skb)
4137 kfree_skb(skb);
4138 return -EINVAL;
4139}
4140
4141/**
4142 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4143 * @wiphy: corestack handler
4144 * @wdev: wireless device
4145 * @data: data
4146 * @data_len: data length
4147 *
4148 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4149 * Validate cmd attributes and send the station info to upper layers.
4150 *
4151 * Return: Success(0) or reason code for failure
4152 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05304153static int
Anurag Chouhan96919482016-07-13 16:36:57 +05304154__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4155 struct wireless_dev *wdev,
4156 const void *data,
4157 int data_len)
4158{
4159 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4160 struct net_device *dev = wdev->netdev;
4161 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4162 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
4163 int32_t status;
4164
4165 ENTER_DEV(dev);
4166 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4167 hdd_err("Command not allowed in FTM mode");
4168 status = -EPERM;
4169 goto out;
4170 }
4171
4172 status = wlan_hdd_validate_context(hdd_ctx);
4173 if (0 != status)
4174 goto out;
4175
4176
4177 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
4178 data, data_len, NULL);
4179 if (status) {
4180 hdd_err("Invalid ATTR");
4181 goto out;
4182 }
4183
4184 /* Parse and fetch Command Type*/
4185 if (tb[STATION_INFO]) {
4186 status = hdd_get_station_info(hdd_ctx, adapter);
4187 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
4188 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
4189 } else {
4190 hdd_err("get station info cmd type failed");
4191 status = -EINVAL;
4192 goto out;
4193 }
4194 EXIT();
4195out:
4196 return status;
4197}
4198
4199/**
4200 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4201 * @wiphy: corestack handler
4202 * @wdev: wireless device
4203 * @data: data
4204 * @data_len: data length
4205 *
4206 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4207 * Validate cmd attributes and send the station info to upper layers.
4208 *
4209 * Return: Success(0) or reason code for failure
4210 */
4211static int32_t
4212hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4213 struct wireless_dev *wdev,
4214 const void *data,
4215 int data_len)
4216{
4217 int ret;
4218
4219 cds_ssr_protect(__func__);
4220 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
4221 cds_ssr_unprotect(__func__);
4222
4223 return ret;
4224}
4225
4226/*
4227 * undef short names defined for get station command
4228 * used by __wlan_hdd_cfg80211_get_station_cmd()
4229 */
4230#undef STATION_INVALID
4231#undef STATION_INFO
4232#undef STATION_ASSOC_FAIL_REASON
4233#undef STATION_MAX
4234
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004235#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4236/**
4237 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4238 * @wiphy: pointer to wireless wiphy structure.
4239 * @wdev: pointer to wireless_dev structure.
4240 * @data: Pointer to the Key data
4241 * @data_len:Length of the data passed
4242 *
4243 * This is called when wlan driver needs to save the keys received via
4244 * vendor specific command.
4245 *
4246 * Return: Return the Success or Failure code.
4247 */
4248static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4249 struct wireless_dev *wdev,
4250 const void *data, int data_len)
4251{
4252 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4253 struct net_device *dev = wdev->netdev;
4254 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4255 hdd_context_t *hdd_ctx_ptr;
4256 int status;
4257
Jeff Johnson1f61b612016-02-12 16:28:33 -08004258 ENTER_DEV(dev);
4259
Anurag Chouhan6d760662016-02-20 16:05:43 +05304260 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 hdd_err("Command not allowed in FTM mode");
4262 return -EPERM;
4263 }
4264
4265 if ((data == NULL) || (data_len == 0) ||
4266 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004267 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004268 return -EINVAL;
4269 }
4270
4271 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4272 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004273 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004274 return -EINVAL;
4275 }
4276
4277 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304278 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004280 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4281 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004282 true,
4283 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304284 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4285 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4287 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4288 return 0;
4289}
4290
4291/**
4292 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4293 * @wiphy: pointer to wireless wiphy structure.
4294 * @wdev: pointer to wireless_dev structure.
4295 * @data: Pointer to the Key data
4296 * @data_len:Length of the data passed
4297 *
4298 * This is called when wlan driver needs to save the keys received via
4299 * vendor specific command.
4300 *
4301 * Return: Return the Success or Failure code.
4302 */
4303static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4304 struct wireless_dev *wdev,
4305 const void *data, int data_len)
4306{
4307 int ret;
4308
4309 cds_ssr_protect(__func__);
4310 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4311 cds_ssr_unprotect(__func__);
4312
4313 return ret;
4314}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004315#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004316
4317static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4318 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4319 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4320 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004321 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322};
4323
4324/**
4325 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4326 * @wiphy: pointer to wireless wiphy structure.
4327 * @wdev: pointer to wireless_dev structure.
4328 * @data: Pointer to the data to be passed via vendor interface
4329 * @data_len:Length of the data to be passed
4330 *
4331 * This is called when wlan driver needs to send wifi driver related info
4332 * (driver/fw version) to the user space application upon request.
4333 *
4334 * Return: Return the Success or Failure code.
4335 */
4336static int
4337__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4338 struct wireless_dev *wdev,
4339 const void *data, int data_len)
4340{
4341 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4342 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004343 tSirVersionString driver_version;
4344 tSirVersionString firmware_version;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004345 const char *hw_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004346 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004347 uint32_t sub_id = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004349 struct sk_buff *reply_skb;
4350 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351
Jeff Johnson1f61b612016-02-12 16:28:33 -08004352 ENTER_DEV(wdev->netdev);
4353
Anurag Chouhan6d760662016-02-20 16:05:43 +05304354 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 hdd_err("Command not allowed in FTM mode");
4356 return -EPERM;
4357 }
4358
4359 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304360 if (status)
4361 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362
4363 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4364 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004365 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004366 return -EINVAL;
4367 }
4368
4369 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004370 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004371 strlcpy(driver_version, QWLAN_VERSIONSTR,
4372 sizeof(driver_version));
4373 skb_len += strlen(driver_version) + 1;
4374 count++;
4375 }
4376
4377 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004378 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4380 &crmid);
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004381 sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
4382 hw_version = hdd_ctx->target_hw_name;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004383 snprintf(firmware_version, sizeof(firmware_version),
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004384 "FW:%d.%d.%d.%d.%d HW:%s", major_spid, minor_spid,
4385 siid, crmid, sub_id, hw_version);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004386 skb_len += strlen(firmware_version) + 1;
4387 count++;
4388 }
4389
4390 if (count == 0) {
4391 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392 return -EINVAL;
4393 }
4394
Ryan Hsu7ac88852016-04-28 10:20:34 -07004395 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4396 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4397
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004398 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004399 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 return -ENOMEM;
4401 }
4402
Ryan Hsu7ac88852016-04-28 10:20:34 -07004403 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4404 if (nla_put_string(reply_skb,
4405 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4406 driver_version))
4407 goto error_nla_fail;
4408 }
4409
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304410 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004411 if (nla_put_string(reply_skb,
4412 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4413 firmware_version))
4414 goto error_nla_fail;
4415 }
4416
4417 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4418 if (nla_put_u32(reply_skb,
4419 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4420 hdd_ctx->radio_index))
4421 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004422 }
4423
4424 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004425
4426error_nla_fail:
4427 hdd_err("nla put fail");
4428 kfree_skb(reply_skb);
4429 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430}
4431
4432/**
4433 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4434 * @wiphy: pointer to wireless wiphy structure.
4435 * @wdev: pointer to wireless_dev structure.
4436 * @data: Pointer to the data to be passed via vendor interface
4437 * @data_len:Length of the data to be passed
4438 *
4439 * This is called when wlan driver needs to send wifi driver related info
4440 * (driver/fw version) to the user space application upon request.
4441 *
4442 * Return: Return the Success or Failure code.
4443 */
4444static int
4445wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4446 struct wireless_dev *wdev,
4447 const void *data, int data_len)
4448{
4449 int ret;
4450
4451 cds_ssr_protect(__func__);
4452 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4453 cds_ssr_unprotect(__func__);
4454
4455 return ret;
4456}
4457
4458/**
4459 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4460 * @wiphy: pointer to wireless wiphy structure.
4461 * @wdev: pointer to wireless_dev structure.
4462 * @data: Pointer to the data to be passed via vendor interface
4463 * @data_len:Length of the data to be passed
4464 *
4465 * This is called by userspace to know the supported logger features
4466 *
4467 * Return: Return the Success or Failure code.
4468 */
4469static int
4470__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4471 struct wireless_dev *wdev,
4472 const void *data, int data_len)
4473{
4474 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4475 int status;
4476 uint32_t features;
4477 struct sk_buff *reply_skb = NULL;
4478
Jeff Johnson1f61b612016-02-12 16:28:33 -08004479 ENTER_DEV(wdev->netdev);
4480
Anurag Chouhan6d760662016-02-20 16:05:43 +05304481 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482 hdd_err("Command not allowed in FTM mode");
4483 return -EPERM;
4484 }
4485
4486 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304487 if (status)
4488 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004489
4490 features = 0;
4491
4492 if (hdd_is_memdump_supported())
4493 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4494 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4495 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4496 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4497
4498 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4499 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4500 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004501 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 return -ENOMEM;
4503 }
4504
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004505 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004506 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4507 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004508 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509 kfree_skb(reply_skb);
4510 return -EINVAL;
4511 }
4512
4513 return cfg80211_vendor_cmd_reply(reply_skb);
4514}
4515
4516/**
4517 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4518 * @wiphy: pointer to wireless wiphy structure.
4519 * @wdev: pointer to wireless_dev structure.
4520 * @data: Pointer to the data to be passed via vendor interface
4521 * @data_len:Length of the data to be passed
4522 *
4523 * This is called by userspace to know the supported logger features
4524 *
4525 * Return: Return the Success or Failure code.
4526 */
4527static int
4528wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4529 struct wireless_dev *wdev,
4530 const void *data, int data_len)
4531{
4532 int ret;
4533
4534 cds_ssr_protect(__func__);
4535 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4536 data, data_len);
4537 cds_ssr_unprotect(__func__);
4538
4539 return ret;
4540}
4541
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004542#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543/**
4544 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304545 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 * @bssid: pointer to bssid of roamed AP.
4547 * @req_rsn_ie: Pointer to request RSN IE
4548 * @req_rsn_len: Length of the request RSN IE
4549 * @rsp_rsn_ie: Pointer to response RSN IE
4550 * @rsp_rsn_len: Length of the response RSN IE
4551 * @roam_info_ptr: Pointer to the roaming related information
4552 *
4553 * This is called when wlan driver needs to send the roaming and
4554 * authorization information after roaming.
4555 *
4556 * The information that would be sent is the request RSN IE, response
4557 * RSN IE and BSSID of the newly roamed AP.
4558 *
4559 * If the Authorized status is authenticated, then additional parameters
4560 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4561 * supplicant.
4562 *
4563 * The supplicant upon receiving this event would ignore the legacy
4564 * cfg80211_roamed call and use the entire information from this event.
4565 * The cfg80211_roamed should still co-exist since the kernel will
4566 * make use of the parameters even if the supplicant ignores it.
4567 *
4568 * Return: Return the Success or Failure code.
4569 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304570int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004571 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4572 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4573{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304574 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004576 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004577 ENTER();
4578
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304579 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004582 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004583 !roam_info_ptr->roamSynchInProgress)
4584 return 0;
4585
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004586 /*
4587 * The user space has issued a disconnect when roaming is in
4588 * progress. The disconnect should be honored gracefully.
4589 * If the roaming is complete and the roam event is sent
4590 * back to the user space, it will get confused as it is
4591 * expecting a disconnect event. So, do not send the event
4592 * and handle the disconnect later.
4593 */
4594 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004595 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004596 return 0;
4597 }
4598
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004599 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304600 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4602 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4603 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004604 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4606 GFP_KERNEL);
4607
4608 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004609 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004610 return -EINVAL;
4611 }
4612
4613 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4614 ETH_ALEN, bssid) ||
4615 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4616 req_rsn_len, req_rsn_ie) ||
4617 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4618 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004619 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620 goto nla_put_failure;
4621 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004622 if (roam_info_ptr->synchAuthStatus ==
4623 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004624 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004625 if (nla_put_u8(skb,
4626 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4627 hdd_err("nla put fail");
4628 goto nla_put_failure;
4629 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004630 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4631 /* if FT or CCKM connection: dont send replay counter */
4632 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4633 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4634 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4635 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4636 nla_put(skb,
4637 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4638 SIR_REPLAY_CTR_LEN,
4639 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004640 hdd_err("non FT/non CCKM connection");
4641 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004642 goto nla_put_failure;
4643 }
4644 if (nla_put(skb,
4645 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4646 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4647 nla_put(skb,
4648 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4649 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4650 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 goto nla_put_failure;
4652 }
4653 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004654 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4656 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004657 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658 goto nla_put_failure;
4659 }
4660 }
4661
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304662 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4663 roam_info_ptr->synchAuthStatus,
4664 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004665
4666 /*
4667 * Add subnet change status if subnet has changed
4668 * 0 = unchanged
4669 * 1 = changed
4670 * 2 = unknown
4671 */
4672 if (roam_info_ptr->subnet_change_status) {
4673 if (nla_put_u8(skb,
4674 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4675 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004676 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004677 goto nla_put_failure;
4678 }
4679 }
4680
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 cfg80211_vendor_event(skb, GFP_KERNEL);
4682 return 0;
4683
4684nla_put_failure:
4685 kfree_skb(skb);
4686 return -EINVAL;
4687}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004688#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689
lifeng907edd62017-05-12 10:10:36 +08004690#define ANT_DIV_PROBE_PERIOD \
4691 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
4692#define ANT_DIV_STAY_PERIOD \
4693 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
4694#define ANT_DIV_SNR_DIFF \
4695 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
4696#define ANT_DIV_PROBE_DWELL_TIME \
4697 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
4698#define ANT_DIV_MGMT_SNR_WEIGHT \
4699 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
4700#define ANT_DIV_DATA_SNR_WEIGHT \
4701 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
4702#define ANT_DIV_ACK_SNR_WEIGHT \
4703 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004704static const struct nla_policy
4705wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4706
4707 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4708 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4709 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304710 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304711 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4712 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004713 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4714 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4715 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4716 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4717 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304718 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08004719 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
4720 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
4721 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
4722 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
4723 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
4724 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
4725 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Ajit Pal Singh747b6802017-05-24 15:42:03 +05304726 [QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004727};
4728
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004729/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304730 * wlan_hdd_add_qcn_ie() - Add QCN IE to a given IE buffer
4731 * @ie_data: IE buffer
4732 * @ie_len: length of the @ie_data
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304733 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304734 * Return: QDF_STATUS
4735 */
4736static QDF_STATUS wlan_hdd_add_qcn_ie(uint8_t *ie_data, uint16_t *ie_len)
4737{
4738 tDot11fIEQCN_IE qcn_ie;
4739 uint8_t qcn_ie_hdr[QCN_IE_HDR_LEN]
4740 = {IE_EID_VENDOR, DOT11F_IE_QCN_IE_MAX_LEN,
4741 0x8C, 0xFD, 0xF0, 0x1};
4742
4743 if (((*ie_len) + QCN_IE_HDR_LEN +
4744 QCN_IE_VERSION_SUBATTR_DATA_LEN) > MAX_DEFAULT_SCAN_IE_LEN) {
4745 hdd_err("IE buffer not enough for QCN IE");
4746 return QDF_STATUS_E_FAILURE;
4747 }
4748
4749 /* Add QCN IE header */
4750 qdf_mem_copy(ie_data + (*ie_len), qcn_ie_hdr, QCN_IE_HDR_LEN);
4751 (*ie_len) += QCN_IE_HDR_LEN;
4752
4753 /* Retrieve Version sub-attribute data */
4754 populate_dot11f_qcn_ie(&qcn_ie);
4755
4756 /* Add QCN IE data[version sub attribute] */
4757 qdf_mem_copy(ie_data + (*ie_len), qcn_ie.version,
4758 (QCN_IE_VERSION_SUBATTR_LEN));
4759 (*ie_len) += (QCN_IE_VERSION_SUBATTR_LEN);
4760
4761 return QDF_STATUS_SUCCESS;
4762}
4763
4764/**
4765 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4766 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304767 * @adapter: Pointer to HDD adapter
4768 * @ie_data: Pointer to Scan IEs buffer
4769 * @ie_len: Length of Scan IEs
4770 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304771 * This API is used to store the default scan ies received from
4772 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
4773 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304774 * Return: 0 on success; error number otherwise
4775 */
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304776static int wlan_hdd_save_default_scan_ies(hdd_context_t *hdd_ctx,
4777 hdd_adapter_t *adapter,
4778 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304779{
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304780 hdd_scaninfo_t *scan_info = &adapter->scan_info;
4781 bool add_qcn_ie = hdd_ctx->config->qcn_ie_support;
4782
4783 if (!scan_info)
4784 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304785
4786 if (scan_info->default_scan_ies) {
4787 qdf_mem_free(scan_info->default_scan_ies);
4788 scan_info->default_scan_ies = NULL;
4789 }
4790
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304791 scan_info->default_scan_ies_len = ie_len;
4792
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304793 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304794 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304795
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304796 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304797 if (!scan_info->default_scan_ies) {
4798 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304799 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304800 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304801
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304802 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
4803 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304804
4805 /* Add QCN IE if g_qcn_ie_support INI is enabled */
4806 if (add_qcn_ie)
4807 wlan_hdd_add_qcn_ie(scan_info->default_scan_ies,
4808 &(scan_info->default_scan_ies_len));
4809
4810 hdd_debug("Saved default scan IE:");
4811 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
4812 (uint8_t *) scan_info->default_scan_ies,
4813 scan_info->default_scan_ies_len);
4814
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304815 return 0;
4816}
4817
4818/**
Ajit Pal Singh747b6802017-05-24 15:42:03 +05304819 * wlan_hdd_handle_restrict_offchan_config() -
4820 * Handle wifi configuration attribute :
4821 * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
4822 * @adapter: Pointer to HDD adapter
4823 * @restrict_offchan: Restrict offchannel setting done by
4824 * application
4825 *
4826 * Return: 0 on success; error number otherwise
4827 */
4828static int wlan_hdd_handle_restrict_offchan_config(hdd_adapter_t *adapter,
4829 u8 restrict_offchan)
4830{
4831 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4832 enum tQDF_ADAPTER_MODE dev_mode = adapter->device_mode;
4833 int ret_val = 0;
4834
4835 if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
4836 hdd_err("Invalid interface type:%d", dev_mode);
4837 return -EINVAL;
4838 }
4839 /*
4840 * To cater to multiple apps we maintain
4841 * a counter to check if restrict_offchannel
4842 * is enabled or disabled per AP/GO vdev.
4843 */
4844 if (restrict_offchan == 1) {
4845 enum policy_mgr_con_mode pmode =
4846 policy_mgr_convert_device_mode_to_qdf_type(dev_mode);
4847 int chan;
4848
4849 adapter->restrict_offchannel_cnt++;
4850 if (adapter->restrict_offchannel_cnt == 1) {
4851 u32 vdev_id = wlan_vdev_get_id(adapter->hdd_vdev);
4852
4853 wlan_vdev_obj_lock(adapter->hdd_vdev);
4854 wlan_vdev_mlme_cap_set(adapter->hdd_vdev,
4855 WLAN_VDEV_C_RESTRICT_OFFCHAN);
4856 wlan_vdev_obj_unlock(adapter->hdd_vdev);
4857 chan = policy_mgr_get_channel(hdd_ctx->hdd_psoc, pmode,
4858 &vdev_id);
4859 if (!chan ||
4860 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, chan)) {
4861 hdd_err("unable to send avoid_freq");
4862 ret_val = -EINVAL;
4863 }
4864 }
4865 } else if ((restrict_offchan == 0) &&
4866 (adapter->restrict_offchannel_cnt > 0)) {
4867 adapter->restrict_offchannel_cnt--;
4868 if (adapter->restrict_offchannel_cnt == 0) {
4869 wlan_vdev_obj_lock(adapter->hdd_vdev);
4870 wlan_vdev_mlme_cap_clear(adapter->hdd_vdev,
4871 WLAN_VDEV_C_RESTRICT_OFFCHAN);
4872 wlan_vdev_obj_unlock(adapter->hdd_vdev);
4873 if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
4874 hdd_err("unable to clear avoid_freq");
4875 ret_val = -EINVAL;
4876 }
4877 }
4878 } else {
4879 ret_val = -EINVAL;
4880 hdd_err("Invalid RESTRICT_OFFCHAN setting");
4881 }
4882
4883 return ret_val;
4884}
4885
4886/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4888 * vendor command
4889 *
4890 * @wiphy: wiphy device pointer
4891 * @wdev: wireless device pointer
4892 * @data: Vendor command data buffer
4893 * @data_len: Buffer length
4894 *
4895 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4896 *
4897 * Return: Error code.
4898 */
4899static int
4900__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4901 struct wireless_dev *wdev,
4902 const void *data,
4903 int data_len)
4904{
4905 struct net_device *dev = wdev->netdev;
4906 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4907 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4908 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4909 int ret_val = 0;
4910 u32 modulated_dtim;
4911 u16 stats_avg_factor;
4912 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304913 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004914 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004915 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304916 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304917 int attr_len;
4918 int access_policy = 0;
4919 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4920 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304921 uint16_t scan_ie_len = 0;
4922 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304923 struct sir_set_tx_rx_aggregation_size request;
4924 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004925 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004926 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004927 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304928 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08004929 uint32_t ant_div_usrcfg;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304930
Jeff Johnson1f61b612016-02-12 16:28:33 -08004931 ENTER_DEV(dev);
4932
Anurag Chouhan6d760662016-02-20 16:05:43 +05304933 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004934 hdd_err("Command not allowed in FTM mode");
4935 return -EPERM;
4936 }
4937
4938 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304939 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004941
4942 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4943 data, data_len,
4944 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004945 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004946 return -EINVAL;
4947 }
4948
Krunal Sonie3531942016-04-12 17:43:53 -07004949 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4950 ftm_capab = nla_get_u32(tb[
4951 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4952 hdd_ctx->config->fine_time_meas_cap =
4953 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4954 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304955 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004956 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004957 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4958 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004959 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004960 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4961 hdd_ctx->config->fine_time_meas_cap);
4962 }
4963
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004964 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4965 modulated_dtim = nla_get_u32(
4966 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4967
4968 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4969 adapter->sessionId,
4970 modulated_dtim);
4971
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304972 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004973 ret_val = -EPERM;
4974 }
4975
Kapil Gupta6213c012016-09-02 19:39:09 +05304976 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4977 qpower = nla_get_u8(
4978 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4979 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4980 ret_val = -EINVAL;
4981 }
4982
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004983 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4984 stats_avg_factor = nla_get_u16(
4985 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4986 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4987 adapter->sessionId,
4988 stats_avg_factor);
4989
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304990 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004991 ret_val = -EPERM;
4992 }
4993
4994
4995 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4996 guard_time = nla_get_u32(
4997 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4998 status = sme_configure_guard_time(hdd_ctx->hHal,
4999 adapter->sessionId,
5000 guard_time);
5001
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305002 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005003 ret_val = -EPERM;
5004 }
5005
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305006 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
5007 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
5008 attr_len = nla_len(
5009 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
5010 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005011 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305012 attr_len);
5013 return -EINVAL;
5014 }
5015
5016 nla_memcpy(&vendor_ie,
5017 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
5018 attr_len);
5019 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005020 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305021 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305022 }
5023
5024 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
5025 access_policy = (int) nla_get_u32(
5026 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
5027 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
5028 (access_policy >
5029 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005030 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305031 access_policy);
5032 return -EINVAL;
5033 }
5034 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005035 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305036 access_policy);
5037 }
5038
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005039 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
5040 retry = nla_get_u8(tb[
5041 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
5042 retry = retry > CFG_NON_AGG_RETRY_MAX ?
5043 CFG_NON_AGG_RETRY_MAX : retry;
5044 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
5045 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5046 retry, PDEV_CMD);
5047 }
5048
5049 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
5050 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
5051 retry = retry > CFG_AGG_RETRY_MAX ?
5052 CFG_AGG_RETRY_MAX : retry;
5053
5054 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
5055 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
5056 CFG_AGG_RETRY_MIN : retry;
5057 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
5058 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5059 retry, PDEV_CMD);
5060 }
5061
5062 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
5063 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
5064 retry = retry > CFG_MGMT_RETRY_MAX ?
5065 CFG_MGMT_RETRY_MAX : retry;
5066 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
5067 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5068 retry, PDEV_CMD);
5069 }
5070
5071 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
5072 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
5073 retry = retry > CFG_CTRL_RETRY_MAX ?
5074 CFG_CTRL_RETRY_MAX : retry;
5075 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
5076 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5077 retry, PDEV_CMD);
5078 }
5079
5080 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
5081 delay = nla_get_u8(tb[
5082 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
5083 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
5084 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08005085 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005086 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
5087 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08005088 abs_delay, PDEV_CMD);
5089 }
5090
5091 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
5092 abs_delay = nla_get_u8(tb[
5093 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
5094 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
5095 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5096 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005097 }
5098
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305099 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
5100 tx_fail_count = nla_get_u32(
5101 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
5102 if (tx_fail_count) {
5103 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
5104 adapter->sessionId, tx_fail_count);
5105 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005106 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305107 status);
5108 return -EINVAL;
5109 }
5110 }
5111 }
5112
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305113 if (vendor_ie_present && access_policy_present) {
5114 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
5115 access_policy =
5116 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305117 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305118 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305119 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305120
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005121 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305122 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
5123 adapter->sessionId, &vendor_ie[0],
5124 access_policy);
5125 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005126 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305127 return -EINVAL;
5128 }
5129 }
5130
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305131 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
5132 set_value = nla_get_u8(
5133 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005134 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305135 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
5136 }
5137
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305138 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
5139 scan_ie_len = nla_len(
5140 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005141 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305142 scan_ie_len, adapter->sessionId,
5143 adapter->device_mode);
5144 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
5145 scan_ie = (uint8_t *) nla_data(tb
5146 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305147
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305148 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
5149 scan_ie, scan_ie_len))
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305150 hdd_err("Failed to save default scan IEs");
5151
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305152 if (adapter->device_mode == QDF_STA_MODE) {
5153 status = sme_set_default_scan_ie(hdd_ctx->hHal,
5154 adapter->sessionId, scan_ie,
5155 scan_ie_len);
5156 if (QDF_STATUS_SUCCESS != status)
5157 ret_val = -EPERM;
5158 }
5159 } else
5160 ret_val = -EPERM;
5161 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05305162
5163 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
5164 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
5165 /* if one is specified, both must be specified */
5166 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
5167 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
5168 hdd_err("Both TX and RX MPDU Aggregation required");
5169 return -EINVAL;
5170 }
5171
5172 request.tx_aggregation_size = nla_get_u8(
5173 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
5174 request.rx_aggregation_size = nla_get_u8(
5175 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
5176 request.vdev_id = adapter->sessionId;
5177
5178 if (request.tx_aggregation_size >=
5179 CFG_TX_AGGREGATION_SIZE_MIN &&
5180 request.tx_aggregation_size <=
5181 CFG_TX_AGGREGATION_SIZE_MAX &&
5182 request.rx_aggregation_size >=
5183 CFG_RX_AGGREGATION_SIZE_MIN &&
5184 request.rx_aggregation_size <=
5185 CFG_RX_AGGREGATION_SIZE_MAX) {
5186 qdf_status = wma_set_tx_rx_aggregation_size(&request);
5187 if (qdf_status != QDF_STATUS_SUCCESS) {
5188 hdd_err("failed to set aggr sizes err %d",
5189 qdf_status);
5190 ret_val = -EPERM;
5191 }
5192 } else {
5193 hdd_err("TX %d RX %d MPDU aggr size not in range",
5194 request.tx_aggregation_size,
5195 request.rx_aggregation_size);
5196 ret_val = -EINVAL;
5197 }
5198 }
5199
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305200 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
5201 uint8_t ignore_assoc_disallowed;
5202
5203 ignore_assoc_disallowed
5204 = nla_get_u8(tb[
5205 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005206 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305207 ignore_assoc_disallowed);
5208 if ((ignore_assoc_disallowed <
5209 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
5210 (ignore_assoc_disallowed >
5211 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
5212 return -EPERM;
5213
5214 sme_update_session_param(hdd_ctx->hHal,
5215 adapter->sessionId,
5216 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
5217 ignore_assoc_disallowed);
5218 }
5219
lifeng907edd62017-05-12 10:10:36 +08005220#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
5221 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
5222
5223#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
5224 ((1<<27)|(snr_diff&0x1fff))
5225
5226#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
5227 ((1<<28)|(probe_dwell_time&0x1fff))
5228
5229#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
5230 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
5231 (ack_snr_weight&0xff))
5232
5233 if (tb[ANT_DIV_PROBE_PERIOD] ||
5234 tb[ANT_DIV_STAY_PERIOD]) {
5235
5236 if (!tb[ANT_DIV_PROBE_PERIOD] ||
5237 !tb[ANT_DIV_STAY_PERIOD]) {
5238 hdd_err("Both probe and stay period required");
5239 return -EINVAL;
5240 }
5241
5242 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
5243 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
5244 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
5245 hdd_debug("ant div set period: %x", ant_div_usrcfg);
5246 ret_val = wma_cli_set_command((int)adapter->sessionId,
5247 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5248 ant_div_usrcfg, PDEV_CMD);
5249 if (ret_val) {
5250 hdd_err("Failed to set ant div period");
5251 return ret_val;
5252 }
5253 }
5254
5255 if (tb[ANT_DIV_SNR_DIFF]) {
5256 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
5257 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
5258 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
5259 ret_val = wma_cli_set_command((int)adapter->sessionId,
5260 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5261 ant_div_usrcfg, PDEV_CMD);
5262 if (ret_val) {
5263 hdd_err("Failed to set ant snr diff");
5264 return ret_val;
5265 }
5266 }
5267
5268 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
5269 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
5270 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
5271 hdd_debug("ant div set probe dewll time: %x",
5272 ant_div_usrcfg);
5273 ret_val = wma_cli_set_command((int)adapter->sessionId,
5274 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5275 ant_div_usrcfg, PDEV_CMD);
5276 if (ret_val) {
5277 hdd_err("Failed to set ant div probe dewll time");
5278 return ret_val;
5279 }
5280 }
5281
5282 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5283 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5284 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5285
5286 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5287 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5288 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5289 hdd_err("Mgmt snr, data snr and ack snr weight are required");
5290 return -EINVAL;
5291 }
5292
5293 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
5294 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
5295 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
5296 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
5297 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
5298 ret_val = wma_cli_set_command((int)adapter->sessionId,
5299 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5300 ant_div_usrcfg, PDEV_CMD);
5301 if (ret_val) {
5302 hdd_err("Failed to set ant div weight");
5303 return ret_val;
5304 }
5305 }
5306
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305307 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL]) {
5308 u8 restrict_offchan = nla_get_u8(
5309 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL]);
5310
5311 hdd_debug("Restrict offchannel:%d", restrict_offchan);
5312 if (restrict_offchan <= 1)
5313 ret_val =
5314 wlan_hdd_handle_restrict_offchan_config(adapter,
5315 restrict_offchan);
5316 else {
5317 ret_val = -EINVAL;
5318 hdd_err("Invalid RESTRICT_OFFCHAN setting");
5319 }
5320 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005321 return ret_val;
5322}
5323
5324/**
5325 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
5326 * vendor command
5327 *
5328 * @wiphy: wiphy device pointer
5329 * @wdev: wireless device pointer
5330 * @data: Vendor command data buffer
5331 * @data_len: Buffer length
5332 *
5333 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
5334 *
5335 * Return: EOK or other error codes.
5336 */
5337static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
5338 struct wireless_dev *wdev,
5339 const void *data,
5340 int data_len)
5341{
5342 int ret;
5343
5344 cds_ssr_protect(__func__);
5345 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
5346 data, data_len);
5347 cds_ssr_unprotect(__func__);
5348
5349 return ret;
5350}
5351
5352static const struct
5353nla_policy
5354qca_wlan_vendor_wifi_logger_start_policy
5355[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
5356 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
5357 = {.type = NLA_U32 },
5358 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
5359 = {.type = NLA_U32 },
5360 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
5361 = {.type = NLA_U32 },
5362};
5363
5364/**
5365 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
5366 * or disable the collection of packet statistics from the firmware
5367 * @wiphy: WIPHY structure pointer
5368 * @wdev: Wireless device structure pointer
5369 * @data: Pointer to the data received
5370 * @data_len: Length of the data received
5371 *
5372 * This function enables or disables the collection of packet statistics from
5373 * the firmware
5374 *
5375 * Return: 0 on success and errno on failure
5376 */
5377static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5378 struct wireless_dev *wdev,
5379 const void *data,
5380 int data_len)
5381{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305382 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5384 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
5385 struct sir_wifi_start_log start_log;
5386
Jeff Johnson1f61b612016-02-12 16:28:33 -08005387 ENTER_DEV(wdev->netdev);
5388
Anurag Chouhan6d760662016-02-20 16:05:43 +05305389 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390 hdd_err("Command not allowed in FTM mode");
5391 return -EPERM;
5392 }
5393
5394 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305395 if (status)
5396 return status;
5397
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05305398 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
5399 hdd_err("Driver Modules are closed, can not start logger");
5400 return -EINVAL;
5401 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005402
5403 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
5404 data, data_len,
5405 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005406 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005407 return -EINVAL;
5408 }
5409
5410 /* Parse and fetch ring id */
5411 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005412 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 return -EINVAL;
5414 }
5415 start_log.ring_id = nla_get_u32(
5416 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005417 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418
5419 /* Parse and fetch verbose level */
5420 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005421 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422 return -EINVAL;
5423 }
5424 start_log.verbose_level = nla_get_u32(
5425 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005426 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005427
5428 /* Parse and fetch flag */
5429 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005430 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 return -EINVAL;
5432 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05305433 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005435 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005436
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305437 /* size is buff size which can be set using iwpriv command*/
5438 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05305439 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305440
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005441 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
5442
5443 if (start_log.ring_id == RING_ID_WAKELOCK) {
5444 /* Start/stop wakelock events */
5445 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
5446 cds_set_wakelock_logging(true);
5447 else
5448 cds_set_wakelock_logging(false);
5449 return 0;
5450 }
5451
5452 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305453 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005454 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005455 status);
5456 return -EINVAL;
5457 }
5458 return 0;
5459}
5460
5461/**
5462 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
5463 * or disable the collection of packet statistics from the firmware
5464 * @wiphy: WIPHY structure pointer
5465 * @wdev: Wireless device structure pointer
5466 * @data: Pointer to the data received
5467 * @data_len: Length of the data received
5468 *
5469 * This function is used to enable or disable the collection of packet
5470 * statistics from the firmware
5471 *
5472 * Return: 0 on success and errno on failure
5473 */
5474static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5475 struct wireless_dev *wdev,
5476 const void *data,
5477 int data_len)
5478{
5479 int ret = 0;
5480
5481 cds_ssr_protect(__func__);
5482 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5483 wdev, data, data_len);
5484 cds_ssr_unprotect(__func__);
5485
5486 return ret;
5487}
5488
5489static const struct
5490nla_policy
5491qca_wlan_vendor_wifi_logger_get_ring_data_policy
5492[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5493 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5494 = {.type = NLA_U32 },
5495};
5496
5497/**
5498 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5499 * @wiphy: WIPHY structure pointer
5500 * @wdev: Wireless device structure pointer
5501 * @data: Pointer to the data received
5502 * @data_len: Length of the data received
5503 *
5504 * This function is used to flush or retrieve the per packet statistics from
5505 * the driver
5506 *
5507 * Return: 0 on success and errno on failure
5508 */
5509static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5510 struct wireless_dev *wdev,
5511 const void *data,
5512 int data_len)
5513{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305514 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005515 uint32_t ring_id;
5516 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5517 struct nlattr *tb
5518 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5519
Jeff Johnson1f61b612016-02-12 16:28:33 -08005520 ENTER_DEV(wdev->netdev);
5521
Anurag Chouhan6d760662016-02-20 16:05:43 +05305522 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523 hdd_err("Command not allowed in FTM mode");
5524 return -EPERM;
5525 }
5526
5527 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305528 if (status)
5529 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530
5531 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5532 data, data_len,
5533 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005534 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005535 return -EINVAL;
5536 }
5537
5538 /* Parse and fetch ring id */
5539 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005540 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005541 return -EINVAL;
5542 }
5543
5544 ring_id = nla_get_u32(
5545 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5546
5547 if (ring_id == RING_ID_PER_PACKET_STATS) {
5548 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005549 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305550 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5551 /*
5552 * As part of DRIVER ring ID, flush both driver and fw logs.
5553 * For other Ring ID's driver doesn't have any rings to flush
5554 */
5555 hdd_notice("Bug report triggered by framework");
5556
5557 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5558 WLAN_LOG_INDICATOR_FRAMEWORK,
5559 WLAN_LOG_REASON_CODE_UNUSED,
5560 true, false);
5561 if (QDF_STATUS_SUCCESS != status) {
5562 hdd_err("Failed to trigger bug report");
5563 return -EINVAL;
5564 }
5565 } else {
5566 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5567 WLAN_LOG_INDICATOR_FRAMEWORK,
5568 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005570 return 0;
5571}
5572
5573/**
5574 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5575 * @wiphy: WIPHY structure pointer
5576 * @wdev: Wireless device structure pointer
5577 * @data: Pointer to the data received
5578 * @data_len: Length of the data received
5579 *
5580 * This function is used to flush or retrieve the per packet statistics from
5581 * the driver
5582 *
5583 * Return: 0 on success and errno on failure
5584 */
5585static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5586 struct wireless_dev *wdev,
5587 const void *data,
5588 int data_len)
5589{
5590 int ret = 0;
5591
5592 cds_ssr_protect(__func__);
5593 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5594 wdev, data, data_len);
5595 cds_ssr_unprotect(__func__);
5596
5597 return ret;
5598}
5599
5600#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5601/**
5602 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5603 * @hdd_ctx: HDD context
5604 * @request_id: [input] request id
5605 * @pattern_id: [output] pattern id
5606 *
5607 * This function loops through request id to pattern id array
5608 * if the slot is available, store the request id and return pattern id
5609 * if entry exists, return the pattern id
5610 *
5611 * Return: 0 on success and errno on failure
5612 */
5613static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5614 uint32_t request_id,
5615 uint8_t *pattern_id)
5616{
5617 uint32_t i;
5618
5619 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5620 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5621 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5622 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5623 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5624 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5625 return 0;
5626 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5627 request_id) {
5628 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5629 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5630 return 0;
5631 }
5632 }
5633 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5634 return -EINVAL;
5635}
5636
5637/**
5638 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5639 * @hdd_ctx: HDD context
5640 * @request_id: [input] request id
5641 * @pattern_id: [output] pattern id
5642 *
5643 * This function loops through request id to pattern id array
5644 * reset request id to 0 (slot available again) and
5645 * return pattern id
5646 *
5647 * Return: 0 on success and errno on failure
5648 */
5649static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5650 uint32_t request_id,
5651 uint8_t *pattern_id)
5652{
5653 uint32_t i;
5654
5655 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5656 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5657 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5658 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5659 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5660 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5661 return 0;
5662 }
5663 }
5664 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5665 return -EINVAL;
5666}
5667
5668
5669/*
5670 * define short names for the global vendor params
5671 * used by __wlan_hdd_cfg80211_offloaded_packets()
5672 */
5673#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5674#define PARAM_REQUEST_ID \
5675 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5676#define PARAM_CONTROL \
5677 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5678#define PARAM_IP_PACKET \
5679 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5680#define PARAM_SRC_MAC_ADDR \
5681 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5682#define PARAM_DST_MAC_ADDR \
5683 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5684#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5685
5686/**
5687 * wlan_hdd_add_tx_ptrn() - add tx pattern
5688 * @adapter: adapter pointer
5689 * @hdd_ctx: hdd context
5690 * @tb: nl attributes
5691 *
5692 * This function reads the NL attributes and forms a AddTxPtrn message
5693 * posts it to SME.
5694 *
5695 */
5696static int
5697wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5698 struct nlattr **tb)
5699{
5700 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305701 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005702 uint32_t request_id, ret, len;
5703 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305704 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005705 uint16_t eth_type = htons(ETH_P_IP);
5706
5707 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005708 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005709 return -ENOTSUPP;
5710 }
5711
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305712 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005713 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005714 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005715 return -ENOMEM;
5716 }
5717
5718 /* Parse and fetch request Id */
5719 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005720 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005721 goto fail;
5722 }
5723
5724 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5725 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005726 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005727 return -EINVAL;
5728 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005729 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005730
5731 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005732 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733 goto fail;
5734 }
5735 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005736 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005737 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005738 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005739 goto fail;
5740 }
5741
5742 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005743 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005744 goto fail;
5745 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005746 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305747 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005748 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005749 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005750
Anurag Chouhanc5548422016-02-24 18:33:27 +05305751 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005752 &adapter->macAddressCurrent)) {
5753 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754 goto fail;
5755 }
5756
5757 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005758 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005759 goto fail;
5760 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305761 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005762 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005763 MAC_ADDR_ARRAY(dst_addr.bytes));
5764
5765 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005766 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005767 goto fail;
5768 }
5769 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005770 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771
5772 if (add_req->ucPtrnSize < 0 ||
5773 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5774 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005775 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005776 add_req->ucPtrnSize);
5777 goto fail;
5778 }
5779
5780 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305781 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305782 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305783 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305784 QDF_MAC_ADDR_SIZE);
5785 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305786 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005787 len += 2;
5788
5789 /*
5790 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5791 * ------------------------------------------------------------
5792 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5793 * ------------------------------------------------------------
5794 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305795 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796 nla_data(tb[PARAM_IP_PACKET]),
5797 add_req->ucPtrnSize);
5798 add_req->ucPtrnSize += len;
5799
5800 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5801 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005802 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005803 goto fail;
5804 }
5805 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005806 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005807
5808 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305809 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005810 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005811 goto fail;
5812 }
5813
5814 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305815 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005816 return 0;
5817
5818fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305819 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820 return -EINVAL;
5821}
5822
5823/**
5824 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5825 * @adapter: adapter pointer
5826 * @hdd_ctx: hdd context
5827 * @tb: nl attributes
5828 *
5829 * This function reads the NL attributes and forms a DelTxPtrn message
5830 * posts it to SME.
5831 *
5832 */
5833static int
5834wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5835 struct nlattr **tb)
5836{
5837 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305838 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005839 uint32_t request_id, ret;
5840 uint8_t pattern_id = 0;
5841
5842 /* Parse and fetch request Id */
5843 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005844 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005845 return -EINVAL;
5846 }
5847 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5848 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005849 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850 return -EINVAL;
5851 }
5852
5853 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5854 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005855 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005856 return -EINVAL;
5857 }
5858
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305859 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005860 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005861 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862 return -ENOMEM;
5863 }
5864
Anurag Chouhanc5548422016-02-24 18:33:27 +05305865 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005866 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005867 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005868 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005869 request_id, del_req->ucPtrnId);
5870
5871 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305872 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005873 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005874 goto fail;
5875 }
5876
5877 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305878 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005879 return 0;
5880
5881fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305882 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005883 return -EINVAL;
5884}
5885
5886
5887/**
5888 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5889 * @wiphy: Pointer to wireless phy
5890 * @wdev: Pointer to wireless device
5891 * @data: Pointer to data
5892 * @data_len: Data length
5893 *
5894 * Return: 0 on success, negative errno on failure
5895 */
5896static int
5897__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5898 struct wireless_dev *wdev,
5899 const void *data,
5900 int data_len)
5901{
5902 struct net_device *dev = wdev->netdev;
5903 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5904 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5905 struct nlattr *tb[PARAM_MAX + 1];
5906 uint8_t control;
5907 int ret;
5908 static const struct nla_policy policy[PARAM_MAX + 1] = {
5909 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5910 [PARAM_CONTROL] = { .type = NLA_U32 },
5911 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305912 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005913 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305914 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915 [PARAM_PERIOD] = { .type = NLA_U32 },
5916 };
5917
Jeff Johnson1f61b612016-02-12 16:28:33 -08005918 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919
Anurag Chouhan6d760662016-02-20 16:05:43 +05305920 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005921 hdd_err("Command not allowed in FTM mode");
5922 return -EPERM;
5923 }
5924
5925 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305926 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928
5929 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005930 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931 return -ENOTSUPP;
5932 }
5933
5934 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005935 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005936 return -EINVAL;
5937 }
5938
5939 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005940 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005941 return -EINVAL;
5942 }
5943 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005944 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005945
5946 if (control == WLAN_START_OFFLOADED_PACKETS)
5947 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005948 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005949 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005950
5951 hdd_err("Invalid control: %d", control);
5952
5953 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005954}
5955
5956/*
5957 * done with short names for the global vendor params
5958 * used by __wlan_hdd_cfg80211_offloaded_packets()
5959 */
5960#undef PARAM_MAX
5961#undef PARAM_REQUEST_ID
5962#undef PARAM_CONTROL
5963#undef PARAM_IP_PACKET
5964#undef PARAM_SRC_MAC_ADDR
5965#undef PARAM_DST_MAC_ADDR
5966#undef PARAM_PERIOD
5967
5968/**
5969 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5970 * @wiphy: wiphy structure pointer
5971 * @wdev: Wireless device structure pointer
5972 * @data: Pointer to the data received
5973 * @data_len: Length of @data
5974 *
5975 * Return: 0 on success; errno on failure
5976 */
5977static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5978 struct wireless_dev *wdev,
5979 const void *data,
5980 int data_len)
5981{
5982 int ret = 0;
5983
5984 cds_ssr_protect(__func__);
5985 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5986 wdev, data, data_len);
5987 cds_ssr_unprotect(__func__);
5988
5989 return ret;
5990}
5991#endif
5992
5993/*
5994 * define short names for the global vendor params
5995 * used by __wlan_hdd_cfg80211_monitor_rssi()
5996 */
5997#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5998#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5999#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
6000#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
6001#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
6002
6003/**
6004 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
6005 * @wiphy: Pointer to wireless phy
6006 * @wdev: Pointer to wireless device
6007 * @data: Pointer to data
6008 * @data_len: Data length
6009 *
6010 * Return: 0 on success, negative errno on failure
6011 */
6012static int
6013__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
6014 struct wireless_dev *wdev,
6015 const void *data,
6016 int data_len)
6017{
6018 struct net_device *dev = wdev->netdev;
6019 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6020 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6021 struct nlattr *tb[PARAM_MAX + 1];
6022 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306023 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006024 int ret;
6025 uint32_t control;
6026 static const struct nla_policy policy[PARAM_MAX + 1] = {
6027 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
6028 [PARAM_CONTROL] = { .type = NLA_U32 },
6029 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
6030 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
6031 };
6032
Jeff Johnson1f61b612016-02-12 16:28:33 -08006033 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006034
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05306035 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
6036 hdd_err("invalid session id: %d", adapter->sessionId);
6037 return -EINVAL;
6038 }
6039
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006040 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306041 if (ret)
6042 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006043
6044 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07006045 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046 return -ENOTSUPP;
6047 }
6048
6049 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006050 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006051 return -EINVAL;
6052 }
6053
6054 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006055 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006056 return -EINVAL;
6057 }
6058
6059 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006060 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006061 return -EINVAL;
6062 }
6063
6064 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
6065 req.session_id = adapter->sessionId;
6066 control = nla_get_u32(tb[PARAM_CONTROL]);
6067
6068 if (control == QCA_WLAN_RSSI_MONITORING_START) {
6069 req.control = true;
6070 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006071 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006072 return -EINVAL;
6073 }
6074
6075 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006076 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006077 return -EINVAL;
6078 }
6079
6080 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
6081 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
6082
6083 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006084 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006085 req.min_rssi, req.max_rssi);
6086 return -EINVAL;
6087 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006088 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006089 req.min_rssi, req.max_rssi);
6090
6091 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
6092 req.control = false;
6093 else {
Jeff Johnson77848112016-06-29 14:52:06 -07006094 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095 return -EINVAL;
6096 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006097 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098 req.request_id, req.session_id, req.control);
6099
6100 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306101 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006102 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006103 return -EINVAL;
6104 }
6105
6106 return 0;
6107}
6108
6109/*
6110 * done with short names for the global vendor params
6111 * used by __wlan_hdd_cfg80211_monitor_rssi()
6112 */
6113#undef PARAM_MAX
6114#undef PARAM_CONTROL
6115#undef PARAM_REQUEST_ID
6116#undef PARAM_MAX_RSSI
6117#undef PARAM_MIN_RSSI
6118
6119/**
6120 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
6121 * @wiphy: wiphy structure pointer
6122 * @wdev: Wireless device structure pointer
6123 * @data: Pointer to the data received
6124 * @data_len: Length of @data
6125 *
6126 * Return: 0 on success; errno on failure
6127 */
6128static int
6129wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
6130 const void *data, int data_len)
6131{
6132 int ret;
6133
6134 cds_ssr_protect(__func__);
6135 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
6136 cds_ssr_unprotect(__func__);
6137
6138 return ret;
6139}
6140
6141/**
6142 * hdd_rssi_threshold_breached() - rssi breached NL event
6143 * @hddctx: HDD context
6144 * @data: rssi breached event data
6145 *
6146 * This function reads the rssi breached event %data and fill in the skb with
6147 * NL attributes and send up the NL event.
6148 *
6149 * Return: none
6150 */
6151void hdd_rssi_threshold_breached(void *hddctx,
6152 struct rssi_breach_event *data)
6153{
6154 hdd_context_t *hdd_ctx = hddctx;
6155 struct sk_buff *skb;
6156
6157 ENTER();
6158
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306159 if (wlan_hdd_validate_context(hdd_ctx))
6160 return;
6161 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006162 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006163 return;
6164 }
6165
6166 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
6167 NULL,
6168 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
6169 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
6170 GFP_KERNEL);
6171
6172 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006173 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174 return;
6175 }
6176
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006177 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006178 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006179 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006180 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
6181
6182 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
6183 data->request_id) ||
6184 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
6185 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
6186 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
6187 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006188 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006189 goto fail;
6190 }
6191
6192 cfg80211_vendor_event(skb, GFP_KERNEL);
6193 return;
6194
6195fail:
6196 kfree_skb(skb);
6197 return;
6198}
6199
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306200static const struct nla_policy
6201ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
6202 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
6203};
6204
6205/**
6206 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
6207 * @wiphy: Pointer to wireless phy
6208 * @wdev: Pointer to wireless device
6209 * @data: Pointer to data
6210 * @data_len: Length of @data
6211 *
6212 * Return: 0 on success, negative errno on failure
6213 */
6214static int
6215__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
6216 struct wireless_dev *wdev,
6217 const void *data, int data_len)
6218{
6219 int status;
6220 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
6221 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07006222 struct net_device *dev = wdev->netdev;
6223 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306224
6225 ENTER_DEV(wdev->netdev);
6226
6227 status = wlan_hdd_validate_context(pHddCtx);
6228 if (0 != status)
6229 return status;
6230 if (!pHddCtx->config->fhostNSOffload) {
6231 hdd_err("ND Offload not supported");
6232 return -EINVAL;
6233 }
6234
6235 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
6236 (struct nlattr *)data,
6237 data_len, ns_offload_set_policy)) {
6238 hdd_err("nla_parse failed");
6239 return -EINVAL;
6240 }
6241
6242 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
6243 hdd_err("ND Offload flag attribute not present");
6244 return -EINVAL;
6245 }
6246
6247 pHddCtx->ns_offload_enable =
6248 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
6249
Dustin Brownd8279d22016-09-07 14:52:57 -07006250 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05306251 if (pHddCtx->ns_offload_enable)
6252 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
6253 else
6254 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07006255
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306256 return 0;
6257}
6258
6259/**
6260 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
6261 * @wiphy: pointer to wireless wiphy structure.
6262 * @wdev: pointer to wireless_dev structure.
6263 * @data: Pointer to the data to be passed via vendor interface
6264 * @data_len:Length of the data to be passed
6265 *
6266 * Return: Return the Success or Failure code.
6267 */
6268static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
6269 struct wireless_dev *wdev,
6270 const void *data, int data_len)
6271{
6272 int ret;
6273
6274 cds_ssr_protect(__func__);
6275 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
6276 cds_ssr_unprotect(__func__);
6277
6278 return ret;
6279}
6280
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006281/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
6282 * @wiphy: Pointer to wireless phy
6283 * @wdev: Pointer to wireless device
6284 * @data: Pointer to data
6285 * @data_len: Data length
6286 *
6287 * This function return the preferred frequency list generated by the policy
6288 * manager.
6289 *
6290 * Return: success or failure code
6291 */
6292static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6293 struct wireless_dev
6294 *wdev, const void *data,
6295 int data_len)
6296{
6297 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6298 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306299 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306300 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006301 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306302 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006303 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006304 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6305 struct sk_buff *reply_skb;
6306
Jeff Johnson1f61b612016-02-12 16:28:33 -08006307 ENTER_DEV(wdev->netdev);
6308
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006309 ret = wlan_hdd_validate_context(hdd_ctx);
6310 if (ret)
6311 return -EINVAL;
6312
6313 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
6314 data, data_len, NULL)) {
6315 hdd_err("Invalid ATTR");
6316 return -EINVAL;
6317 }
6318
6319 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
6320 hdd_err("attr interface type failed");
6321 return -EINVAL;
6322 }
6323
6324 intf_mode = nla_get_u32(tb
6325 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
6326
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006327 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006328 hdd_err("Invalid interface type");
6329 return -EINVAL;
6330 }
6331
6332 hdd_debug("Userspace requested pref freq list");
6333
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006334 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
6335 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05306336 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306337 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006338 hdd_err("Get pcl failed");
6339 return -EINVAL;
6340 }
6341
6342 /* convert channel number to frequency */
6343 for (i = 0; i < pcl_len; i++) {
6344 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
6345 freq_list[i] =
6346 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006347 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006348 else
6349 freq_list[i] =
6350 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006351 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006352 }
6353
6354 /* send the freq_list back to supplicant */
6355 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
6356 sizeof(u32) *
6357 pcl_len +
6358 NLMSG_HDRLEN);
6359
6360 if (!reply_skb) {
6361 hdd_err("Allocate reply_skb failed");
6362 return -EINVAL;
6363 }
6364
6365 if (nla_put_u32(reply_skb,
6366 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
6367 intf_mode) ||
6368 nla_put(reply_skb,
6369 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
6370 sizeof(uint32_t) * pcl_len,
6371 freq_list)) {
6372 hdd_err("nla put fail");
6373 kfree_skb(reply_skb);
6374 return -EINVAL;
6375 }
6376
6377 return cfg80211_vendor_cmd_reply(reply_skb);
6378}
6379
6380/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
6381 * @wiphy: Pointer to wireless phy
6382 * @wdev: Pointer to wireless device
6383 * @data: Pointer to data
6384 * @data_len: Data length
6385 *
6386 * This function return the preferred frequency list generated by the policy
6387 * manager.
6388 *
6389 * Return: success or failure code
6390 */
6391static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6392 struct wireless_dev
6393 *wdev, const void *data,
6394 int data_len)
6395{
6396 int ret = 0;
6397
6398 cds_ssr_protect(__func__);
6399 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
6400 data, data_len);
6401 cds_ssr_unprotect(__func__);
6402
6403 return ret;
6404}
6405
6406/**
6407 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6408 * @wiphy: Pointer to wireless phy
6409 * @wdev: Pointer to wireless device
6410 * @data: Pointer to data
6411 * @data_len: Data length
6412 *
6413 * Return: 0 on success, negative errno on failure
6414 */
6415static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6416 struct wireless_dev *wdev,
6417 const void *data,
6418 int data_len)
6419{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05306420 struct net_device *ndev = wdev->netdev;
6421 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006422 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6423 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006424 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006425 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6426 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006427
Jeff Johnson1f61b612016-02-12 16:28:33 -08006428 ENTER_DEV(ndev);
6429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006430 ret = wlan_hdd_validate_context(hdd_ctx);
6431 if (ret)
6432 return ret;
6433
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006434 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
6435 data, data_len, NULL)) {
6436 hdd_err("Invalid ATTR");
6437 return -EINVAL;
6438 }
6439
6440 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
6441 hdd_err("attr interface type failed");
6442 return -EINVAL;
6443 }
6444
6445 intf_mode = nla_get_u32(tb
6446 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
6447
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006448 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006449 hdd_err("Invalid interface type");
6450 return -EINVAL;
6451 }
6452
6453 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
6454 hdd_err("attr probable freq failed");
6455 return -EINVAL;
6456 }
6457
6458 channel_hint = cds_freq_to_chan(nla_get_u32(tb
6459 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
6460
6461 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006462 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006463 channel_hint, HW_MODE_20_MHZ)) {
6464 hdd_err("Set channel hint failed due to concurrency check");
6465 return -EINVAL;
6466 }
6467
Krunal Soni09e55032016-06-07 10:06:55 -07006468 if (0 != wlan_hdd_check_remain_on_channel(adapter))
6469 hdd_warn("Remain On Channel Pending");
6470
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006471 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006472 if (!QDF_IS_STATUS_SUCCESS(ret))
6473 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006474
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006475 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
6476 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07006477 SIR_UPDATE_REASON_SET_OPER_CHAN);
6478 if (QDF_STATUS_E_FAILURE == ret) {
6479 /* return in the failure case */
6480 hdd_err("ERROR: connections update failed!!");
6481 return -EINVAL;
6482 }
6483
6484 if (QDF_STATUS_SUCCESS == ret) {
6485 /*
6486 * Success is the only case for which we expect hw mode
6487 * change to take place, hence we need to wait.
6488 * For any other return value it should be a pass
6489 * through
6490 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006491 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006492 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6493 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006494 return -EINVAL;
6495 }
6496
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006497 }
6498
6499 return 0;
6500}
6501
6502/**
6503 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6504 * @wiphy: Pointer to wireless phy
6505 * @wdev: Pointer to wireless device
6506 * @data: Pointer to data
6507 * @data_len: Data length
6508 *
6509 * Return: 0 on success, negative errno on failure
6510 */
6511static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6512 struct wireless_dev *wdev,
6513 const void *data,
6514 int data_len)
6515{
6516 int ret = 0;
6517
6518 cds_ssr_protect(__func__);
6519 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6520 data, data_len);
6521 cds_ssr_unprotect(__func__);
6522
6523 return ret;
6524}
6525
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306526static const struct
6527nla_policy
6528qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6529 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6530};
6531
6532/**
6533 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6534 * @wiphy: WIPHY structure pointer
6535 * @wdev: Wireless device structure pointer
6536 * @data: Pointer to the data received
6537 * @data_len: Length of the data received
6538 *
6539 * This function is used to get link properties like nss, rate flags and
6540 * operating frequency for the active connection with the given peer.
6541 *
6542 * Return: 0 on success and errno on failure
6543 */
6544static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6545 struct wireless_dev *wdev,
6546 const void *data,
6547 int data_len)
6548{
6549 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6550 struct net_device *dev = wdev->netdev;
6551 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6552 hdd_station_ctx_t *hdd_sta_ctx;
6553 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306554 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306555 uint32_t sta_id;
6556 struct sk_buff *reply_skb;
6557 uint32_t rate_flags = 0;
6558 uint8_t nss;
6559 uint8_t final_rate_flags = 0;
6560 uint32_t freq;
6561
Jeff Johnson1f61b612016-02-12 16:28:33 -08006562 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306563
Anurag Chouhan6d760662016-02-20 16:05:43 +05306564 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306565 hdd_err("Command not allowed in FTM mode");
6566 return -EPERM;
6567 }
6568
6569 if (0 != wlan_hdd_validate_context(hdd_ctx))
6570 return -EINVAL;
6571
6572 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6573 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006574 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306575 return -EINVAL;
6576 }
6577
6578 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006579 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306580 adapter->device_mode);
6581 return -EINVAL;
6582 }
6583
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306584 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306585 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006586 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306587 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6588
Krunal Sonib4326f22016-03-10 13:05:51 -08006589 if (adapter->device_mode == QDF_STA_MODE ||
6590 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306591 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6592 if ((hdd_sta_ctx->conn_info.connState !=
6593 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306594 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306595 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006596 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306597 MAC_ADDR_ARRAY(peer_mac));
6598 return -EINVAL;
6599 }
6600
6601 nss = hdd_sta_ctx->conn_info.nss;
6602 freq = cds_chan_to_freq(
6603 hdd_sta_ctx->conn_info.operationChannel);
6604 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006605 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6606 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306607
6608 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6609 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306610 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306611 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306612 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306613 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306614 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306615 break;
6616 }
6617
6618 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006619 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306620 MAC_ADDR_ARRAY(peer_mac));
6621 return -EINVAL;
6622 }
6623
6624 nss = adapter->aStaInfo[sta_id].nss;
6625 freq = cds_chan_to_freq(
6626 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6627 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6628 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006629 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306630 MAC_ADDR_ARRAY(peer_mac));
6631 return -EINVAL;
6632 }
6633
6634 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6635 if (rate_flags & eHAL_TX_RATE_VHT80) {
6636 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006637#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306638 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006639#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306640 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6641 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006642#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306643 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006644#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306645 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6646 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6647 } else if (rate_flags &
6648 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6649 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006650#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306651 if (rate_flags & eHAL_TX_RATE_HT40)
6652 final_rate_flags |=
6653 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006654#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306655 }
6656
6657 if (rate_flags & eHAL_TX_RATE_SGI) {
6658 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6659 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6660 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6661 }
6662 }
6663
6664 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6665 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6666
6667 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006668 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306669 return -EINVAL;
6670 }
6671
6672 if (nla_put_u8(reply_skb,
6673 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6674 nss) ||
6675 nla_put_u8(reply_skb,
6676 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6677 final_rate_flags) ||
6678 nla_put_u32(reply_skb,
6679 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6680 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006681 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306682 kfree_skb(reply_skb);
6683 return -EINVAL;
6684 }
6685
6686 return cfg80211_vendor_cmd_reply(reply_skb);
6687}
6688
6689/**
6690 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6691 * properties.
6692 * @wiphy: WIPHY structure pointer
6693 * @wdev: Wireless device structure pointer
6694 * @data: Pointer to the data received
6695 * @data_len: Length of the data received
6696 *
6697 * This function is used to get link properties like nss, rate flags and
6698 * operating frequency for the active connection with the given peer.
6699 *
6700 * Return: 0 on success and errno on failure
6701 */
6702static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6703 struct wireless_dev *wdev,
6704 const void *data,
6705 int data_len)
6706{
6707 int ret = 0;
6708
6709 cds_ssr_protect(__func__);
6710 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6711 wdev, data, data_len);
6712 cds_ssr_unprotect(__func__);
6713
6714 return ret;
6715}
6716
Peng Xu278d0122015-09-24 16:34:17 -07006717static const struct
6718nla_policy
6719qca_wlan_vendor_ota_test_policy
6720[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6721 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6722};
6723
6724/**
6725 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6726 * @wiphy: Pointer to wireless phy
6727 * @wdev: Pointer to wireless device
6728 * @data: Pointer to data
6729 * @data_len: Data length
6730 *
6731 * Return: 0 on success, negative errno on failure
6732 */
6733static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6734 struct wireless_dev *wdev,
6735 const void *data,
6736 int data_len)
6737{
6738 struct net_device *dev = wdev->netdev;
6739 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6740 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6741 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6742 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6743 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306744 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006745 uint32_t current_roam_state;
6746
Jeff Johnson1f61b612016-02-12 16:28:33 -08006747 ENTER_DEV(dev);
6748
Anurag Chouhan6d760662016-02-20 16:05:43 +05306749 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006750 hdd_err("Command not allowed in FTM mode");
6751 return -EPERM;
6752 }
6753
6754 if (0 != wlan_hdd_validate_context(hdd_ctx))
6755 return -EINVAL;
6756
6757 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6758 data, data_len,
6759 qca_wlan_vendor_ota_test_policy)) {
6760 hdd_err("invalid attr");
6761 return -EINVAL;
6762 }
6763
6764 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6765 hdd_err("attr ota test failed");
6766 return -EINVAL;
6767 }
6768
6769 ota_enable = nla_get_u8(
6770 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6771
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006772 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006773 if (ota_enable != 1) {
6774 hdd_err("Invalid value, only enable test mode is supported!");
6775 return -EINVAL;
6776 }
6777
6778 current_roam_state =
6779 sme_get_current_roam_state(hal, adapter->sessionId);
6780 status = sme_stop_roaming(hal, adapter->sessionId,
6781 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306782 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006783 hdd_err("Enable/Disable roaming failed");
6784 return -EINVAL;
6785 }
6786
6787 status = sme_ps_enable_disable(hal, adapter->sessionId,
6788 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306789 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006790 hdd_err("Enable/Disable power save failed");
6791 /* restore previous roaming setting */
6792 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6793 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6794 status = sme_start_roaming(hal, adapter->sessionId,
6795 eCsrHddIssued);
6796 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6797 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6798 status = sme_stop_roaming(hal, adapter->sessionId,
6799 eCsrHddIssued);
6800
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306801 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006802 hdd_err("Restoring roaming state failed");
6803
6804 return -EINVAL;
6805 }
6806
6807
6808 return 0;
6809}
6810
6811/**
6812 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6813 * @wiphy: Pointer to wireless phy
6814 * @wdev: Pointer to wireless device
6815 * @data: Pointer to data
6816 * @data_len: Data length
6817 *
6818 * Return: 0 on success, negative errno on failure
6819 */
6820static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6821 struct wireless_dev *wdev,
6822 const void *data,
6823 int data_len)
6824{
6825 int ret = 0;
6826
6827 cds_ssr_protect(__func__);
6828 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6829 cds_ssr_unprotect(__func__);
6830
6831 return ret;
6832}
6833
Peng Xu4d67c8f2015-10-16 16:02:26 -07006834/**
6835 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6836 * @wiphy: Pointer to wireless phy
6837 * @wdev: Pointer to wireless device
6838 * @data: Pointer to data
6839 * @data_len: Data length
6840 *
6841 * Return: 0 on success, negative errno on failure
6842 */
6843static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6844 struct wireless_dev *wdev,
6845 const void *data,
6846 int data_len)
6847{
6848 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6849 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006850 hdd_adapter_t *adapter;
6851 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006852 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6853 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006854 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006855
Jeff Johnson1f61b612016-02-12 16:28:33 -08006856 ENTER_DEV(dev);
6857
Peng Xu4d67c8f2015-10-16 16:02:26 -07006858 ret = wlan_hdd_validate_context(hdd_ctx);
6859 if (ret)
6860 return ret;
6861
6862 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6863
6864 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6865 data, data_len, NULL)) {
6866 hdd_err("Invalid ATTR");
6867 return -EINVAL;
6868 }
6869
6870 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6871 hdd_err("attr tx power scale failed");
6872 return -EINVAL;
6873 }
6874
6875 scale_value = nla_get_u8(tb
6876 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6877
6878 if (scale_value > MAX_TXPOWER_SCALE) {
6879 hdd_err("Invalid tx power scale level");
6880 return -EINVAL;
6881 }
6882
Peng Xu62c8c432016-05-09 15:23:02 -07006883 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006884
Peng Xu62c8c432016-05-09 15:23:02 -07006885 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006886 hdd_err("Set tx power scale failed");
6887 return -EINVAL;
6888 }
6889
6890 return 0;
6891}
6892
6893/**
6894 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6895 * @wiphy: Pointer to wireless phy
6896 * @wdev: Pointer to wireless device
6897 * @data: Pointer to data
6898 * @data_len: Data length
6899 *
6900 * Return: 0 on success, negative errno on failure
6901 */
6902static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6903 struct wireless_dev *wdev,
6904 const void *data,
6905 int data_len)
6906{
Peng Xu62c8c432016-05-09 15:23:02 -07006907 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006908
6909 cds_ssr_protect(__func__);
6910 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6911 data, data_len);
6912 cds_ssr_unprotect(__func__);
6913
6914 return ret;
6915}
6916
6917/**
6918 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6919 * @wiphy: Pointer to wireless phy
6920 * @wdev: Pointer to wireless device
6921 * @data: Pointer to data
6922 * @data_len: Data length
6923 *
6924 * Return: 0 on success, negative errno on failure
6925 */
6926static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6927 struct wireless_dev *wdev,
6928 const void *data,
6929 int data_len)
6930{
6931 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6932 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006933 hdd_adapter_t *adapter;
6934 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006935 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6936 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006937 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006938
Jeff Johnson1f61b612016-02-12 16:28:33 -08006939 ENTER_DEV(dev);
6940
Peng Xu4d67c8f2015-10-16 16:02:26 -07006941 ret = wlan_hdd_validate_context(hdd_ctx);
6942 if (ret)
6943 return ret;
6944
6945 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6946
6947 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6948 data, data_len, NULL)) {
6949 hdd_err("Invalid ATTR");
6950 return -EINVAL;
6951 }
6952
6953 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6954 hdd_err("attr tx power decrease db value failed");
6955 return -EINVAL;
6956 }
6957
6958 scale_value = nla_get_u8(tb
6959 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6960
Peng Xu62c8c432016-05-09 15:23:02 -07006961 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6962 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006963
Peng Xu62c8c432016-05-09 15:23:02 -07006964 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006965 hdd_err("Set tx power decrease db failed");
6966 return -EINVAL;
6967 }
6968
6969 return 0;
6970}
6971
6972/**
6973 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6974 * @wiphy: Pointer to wireless phy
6975 * @wdev: Pointer to wireless device
6976 * @data: Pointer to data
6977 * @data_len: Data length
6978 *
6979 * Return: 0 on success, negative errno on failure
6980 */
6981static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6982 struct wireless_dev *wdev,
6983 const void *data,
6984 int data_len)
6985{
Peng Xu62c8c432016-05-09 15:23:02 -07006986 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006987
6988 cds_ssr_protect(__func__);
6989 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6990 data, data_len);
6991 cds_ssr_unprotect(__func__);
6992
6993 return ret;
6994}
Peng Xu8fdaa492016-06-22 10:20:47 -07006995
6996/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306997 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6998 * @wiphy: Pointer to wireless phy
6999 * @wdev: Pointer to wireless device
7000 * @data: Pointer to data
7001 * @data_len: Data length
7002 *
7003 * Processes the conditional channel switch request and invokes the helper
7004 * APIs to process the channel switch request.
7005 *
7006 * Return: 0 on success, negative errno on failure
7007 */
7008static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
7009 struct wireless_dev *wdev,
7010 const void *data,
7011 int data_len)
7012{
7013 int ret;
7014 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7015 struct net_device *dev = wdev->netdev;
7016 hdd_adapter_t *adapter;
7017 struct nlattr
7018 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
7019 uint32_t freq_len, i;
7020 uint32_t *freq;
7021 uint8_t chans[QDF_MAX_NUM_CHAN];
7022
7023 ENTER_DEV(dev);
7024
7025 ret = wlan_hdd_validate_context(hdd_ctx);
7026 if (ret)
7027 return ret;
7028
7029 if (!hdd_ctx->config->enableDFSMasterCap) {
7030 hdd_err("DFS master capability is not present in the driver");
7031 return -EINVAL;
7032 }
7033
7034 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7035 hdd_err("Command not allowed in FTM mode");
7036 return -EPERM;
7037 }
7038
7039 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7040 if (adapter->device_mode != QDF_SAP_MODE) {
7041 hdd_err("Invalid device mode %d", adapter->device_mode);
7042 return -EINVAL;
7043 }
7044
7045 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
7046 data, data_len, NULL)) {
7047 hdd_err("Invalid ATTR");
7048 return -EINVAL;
7049 }
7050
7051 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
7052 hdd_err("Frequency list is missing");
7053 return -EINVAL;
7054 }
7055
7056 freq_len = nla_len(
7057 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
7058 sizeof(uint32_t);
7059
7060 if (freq_len > QDF_MAX_NUM_CHAN) {
7061 hdd_err("insufficient space to hold channels");
7062 return -ENOMEM;
7063 }
7064
7065 hdd_debug("freq_len=%d", freq_len);
7066
7067 freq = nla_data(
7068 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
7069
7070
7071 for (i = 0; i < freq_len; i++) {
7072 if (freq[i] == 0)
7073 chans[i] = 0;
7074 else
7075 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7076
7077 hdd_debug("freq[%d]=%d", i, freq[i]);
7078 }
7079
7080 /*
7081 * The input frequency list from user space is designed to be a
7082 * priority based frequency list. This is only to accommodate any
7083 * future request. But, current requirement is only to perform CAC
7084 * on a single channel. So, the first entry from the list is picked.
7085 *
7086 * If channel is zero, any channel in the available outdoor regulatory
7087 * domain will be selected.
7088 */
7089 ret = wlan_hdd_request_pre_cac(chans[0]);
7090 if (ret) {
7091 hdd_err("pre cac request failed with reason:%d", ret);
7092 return ret;
7093 }
7094
7095 return 0;
7096}
7097
7098/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007099 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
7100 * @wiphy: Pointer to wireless phy
7101 * @wdev: Pointer to wireless device
7102 * @data: Pointer to data
7103 * @data_len: Data length
7104 *
7105 * This function is to process the p2p listen offload start vendor
7106 * command. It parses the input parameters and invoke WMA API to
7107 * send the command to firmware.
7108 *
7109 * Return: 0 on success, negative errno on failure
7110 */
7111static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
7112 struct wireless_dev *wdev,
7113 const void *data,
7114 int data_len)
7115{
7116 int ret;
7117 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7118 struct net_device *dev = wdev->netdev;
7119 hdd_adapter_t *adapter;
7120 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
7121 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07007122
7123 ENTER_DEV(dev);
7124
7125 ret = wlan_hdd_validate_context(hdd_ctx);
7126 if (ret)
7127 return ret;
7128
7129 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7130 hdd_err("Command not allowed in FTM mode");
7131 return -EPERM;
7132 }
7133
7134 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7135 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
7136 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
7137 (adapter->device_mode != QDF_P2P_GO_MODE)) {
7138 hdd_err("Invalid device mode %d", adapter->device_mode);
7139 return -EINVAL;
7140 }
7141
7142 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
7143 data, data_len, NULL)) {
7144 hdd_err("Invalid ATTR");
7145 return -EINVAL;
7146 }
7147
7148 memset(&params, 0, sizeof(params));
7149
7150 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
7151 params.ctl_flags = 1; /* set to default value */
7152 else
7153 params.ctl_flags = nla_get_u32(tb
7154 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
7155
7156 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
7157 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
7158 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
7159 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
7160 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
7161 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
7162 hdd_err("Attribute parsing failed");
7163 return -EINVAL;
7164 }
7165
7166 params.vdev_id = adapter->sessionId;
7167 params.freq = nla_get_u32(tb
7168 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
7169 if ((params.freq != 2412) && (params.freq != 2437) &&
7170 (params.freq != 2462)) {
7171 hdd_err("Invalid listening channel: %d", params.freq);
7172 return -EINVAL;
7173 }
7174
7175 params.period = nla_get_u32(tb
7176 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
7177 if (!((params.period > 0) && (params.period < UINT_MAX))) {
7178 hdd_err("Invalid period: %d", params.period);
7179 return -EINVAL;
7180 }
7181
7182 params.interval = nla_get_u32(tb
7183 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
7184 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
7185 hdd_err("Invalid interval: %d", params.interval);
7186 return -EINVAL;
7187 }
7188
7189 params.count = nla_get_u32(tb
7190 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08007191 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07007192 hdd_err("Invalid count: %d", params.count);
7193 return -EINVAL;
7194 }
7195
7196 params.device_types = nla_data(tb
7197 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
7198 if (params.device_types == NULL) {
7199 hdd_err("Invalid device types");
7200 return -EINVAL;
7201 }
7202
7203 params.dev_types_len = nla_len(tb
7204 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
7205 if (params.dev_types_len < 8) {
7206 hdd_err("Invalid device type length: %d", params.dev_types_len);
7207 return -EINVAL;
7208 }
7209
7210 params.probe_resp_tmplt = nla_data(tb
7211 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
7212 if (params.probe_resp_tmplt == NULL) {
7213 hdd_err("Invalid probe response template");
7214 return -EINVAL;
7215 }
7216
7217 params.probe_resp_len = nla_len(tb
7218 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
7219 if (params.probe_resp_len == 0) {
7220 hdd_err("Invalid probe resp template length: %d",
7221 params.probe_resp_len);
7222 return -EINVAL;
7223 }
7224
7225 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
7226 params.freq, params.period, params.interval, params.count);
7227
Wu Gao9a704f42017-03-10 18:42:11 +08007228 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07007229}
7230
7231
7232/**
7233 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
7234 * @wiphy: Pointer to wireless phy
7235 * @wdev: Pointer to wireless device
7236 * @data: Pointer to data
7237 * @data_len: Data length
7238 *
7239 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
7240 * to process p2p listen offload start vendor command.
7241 *
7242 * Return: 0 on success, negative errno on failure
7243 */
7244static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
7245 struct wireless_dev *wdev,
7246 const void *data,
7247 int data_len)
7248{
7249 int ret = 0;
7250
7251 cds_ssr_protect(__func__);
7252 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
7253 data, data_len);
7254 cds_ssr_unprotect(__func__);
7255
7256 return ret;
7257}
7258
7259/**
7260 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7261 * @wiphy: Pointer to wireless phy
7262 * @wdev: Pointer to wireless device
7263 * @data: Pointer to data
7264 * @data_len: Data length
7265 *
7266 * This function is to process the p2p listen offload stop vendor
7267 * command. It invokes WMA API to send command to firmware.
7268 *
7269 * Return: 0 on success, negative errno on failure
7270 */
7271static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7272 struct wireless_dev *wdev,
7273 const void *data,
7274 int data_len)
7275{
Peng Xu8fdaa492016-06-22 10:20:47 -07007276 hdd_adapter_t *adapter;
7277 struct net_device *dev = wdev->netdev;
7278
7279 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7280 hdd_err("Command not allowed in FTM mode");
7281 return -EPERM;
7282 }
7283
7284 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7285 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
7286 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
7287 (adapter->device_mode != QDF_P2P_GO_MODE)) {
7288 hdd_err("Invalid device mode");
7289 return -EINVAL;
7290 }
7291
Wu Gao9a704f42017-03-10 18:42:11 +08007292 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07007293}
7294
7295/**
7296 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7297 * @wiphy: Pointer to wireless phy
7298 * @wdev: Pointer to wireless device
7299 * @data: Pointer to data
7300 * @data_len: Data length
7301 *
7302 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
7303 * to process p2p listen offload stop vendor command.
7304 *
7305 * Return: 0 on success, negative errno on failure
7306 */
7307static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7308 struct wireless_dev *wdev,
7309 const void *data,
7310 int data_len)
7311{
7312 int ret = 0;
7313
7314 cds_ssr_protect(__func__);
7315 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
7316 data, data_len);
7317 cds_ssr_unprotect(__func__);
7318
7319 return ret;
7320}
7321
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307322/**
7323 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
7324 * @wiphy: Pointer to wireless phy
7325 * @wdev: Pointer to wireless device
7326 * @data: Pointer to data
7327 * @data_len: Data length
7328 *
7329 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
7330 * to process the conditional channel switch request.
7331 *
7332 * Return: 0 on success, negative errno on failure
7333 */
7334static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
7335 struct wireless_dev *wdev,
7336 const void *data,
7337 int data_len)
7338{
7339 int ret;
7340
7341 cds_ssr_protect(__func__);
7342 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
7343 data, data_len);
7344 cds_ssr_unprotect(__func__);
7345
7346 return ret;
7347}
7348
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307349/*
7350 * define short names for the global vendor params
7351 * used by __wlan_hdd_cfg80211_bpf_offload()
7352 */
7353#define BPF_INVALID \
7354 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
7355#define BPF_SET_RESET \
7356 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
7357#define BPF_VERSION \
7358 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
7359#define BPF_FILTER_ID \
7360 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
7361#define BPF_PACKET_SIZE \
7362 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
7363#define BPF_CURRENT_OFFSET \
7364 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
7365#define BPF_PROGRAM \
7366 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
7367#define BPF_MAX \
7368 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07007369
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307370static const struct nla_policy
7371wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
7372 [BPF_SET_RESET] = {.type = NLA_U32},
7373 [BPF_VERSION] = {.type = NLA_U32},
7374 [BPF_FILTER_ID] = {.type = NLA_U32},
7375 [BPF_PACKET_SIZE] = {.type = NLA_U32},
7376 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
7377 [BPF_PROGRAM] = {.type = NLA_U8},
7378};
7379
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007380struct bpf_offload_priv {
7381 struct sir_bpf_get_offload bpf_get_offload;
7382};
7383
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307384/**
7385 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007386 * @context: opaque context originally passed to SME. HDD always passes
7387 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307388 * @bpf_get_offload: struct for get offload
7389 *
7390 * This function receives the response/data from the lower layer and
7391 * checks to see if the thread is still waiting then post the results to
7392 * upper layer, if the request has timed out then ignore.
7393 *
7394 * Return: None
7395 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007396static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007397 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307398{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007399 struct hdd_request *request;
7400 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307401
7402 ENTER();
7403
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007404 request = hdd_request_get(context);
7405 if (!request) {
7406 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307407 return;
7408 }
7409
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007410 priv = hdd_request_priv(request);
7411 priv->bpf_get_offload = *data;
7412 hdd_request_complete(request);
7413 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307414}
7415
7416/**
7417 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
7418 * @hdd_context: hdd_context
7419 * @bpf_get_offload: struct for get offload
7420 *
7421 * Return: 0 on success, error number otherwise.
7422 */
7423static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
7424 struct sir_bpf_get_offload *bpf_get_offload)
7425{
7426 struct sk_buff *skb;
7427 uint32_t nl_buf_len;
7428
7429 ENTER();
7430
7431 nl_buf_len = NLMSG_HDRLEN;
7432 nl_buf_len +=
7433 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
7434 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
7435
7436 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7437 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007438 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307439 return -ENOMEM;
7440 }
7441
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007442 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307443 bpf_get_offload->bpf_version,
7444 bpf_get_offload->max_bytes_for_bpf_inst);
7445
7446 if (nla_put_u32(skb, BPF_PACKET_SIZE,
7447 bpf_get_offload->max_bytes_for_bpf_inst) ||
7448 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007449 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307450 goto nla_put_failure;
7451 }
7452
7453 cfg80211_vendor_cmd_reply(skb);
7454 EXIT();
7455 return 0;
7456
7457nla_put_failure:
7458 kfree_skb(skb);
7459 return -EINVAL;
7460}
7461
7462/**
7463 * hdd_get_bpf_offload - Get BPF offload Capabilities
7464 * @hdd_ctx: Hdd context
7465 *
7466 * Return: 0 on success, errno on failure
7467 */
7468static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
7469{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307470 QDF_STATUS status;
7471 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007472 void *cookie;
7473 struct hdd_request *request;
7474 struct bpf_offload_priv *priv;
7475 static const struct hdd_request_params params = {
7476 .priv_size = sizeof(*priv),
7477 .timeout_ms = WLAN_WAIT_TIME_BPF,
7478 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307479
7480 ENTER();
7481
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007482 request = hdd_request_alloc(&params);
7483 if (!request) {
7484 hdd_err("Unable to allocate request");
7485 return -EINVAL;
7486 }
7487 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307488
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007489 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7490 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007491 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307492 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007493 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007494 ret = qdf_status_to_os_return(status);
7495 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307496 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007497 ret = hdd_request_wait_for_response(request);
7498 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007499 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007500 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307501 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007502 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307503 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007504 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307505 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007506 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307507
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007508cleanup:
7509 /*
7510 * either we never sent a request to SME, we sent a request to
7511 * SME and timed out, or we sent a request to SME, received a
7512 * response from SME, and posted the response to userspace.
7513 * regardless we are done with the request.
7514 */
7515 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307516 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007517
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307518 return ret;
7519}
7520
7521/**
7522 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7523 * @hdd_ctx: Hdd context
7524 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307525 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307526 *
7527 * Return: 0 on success; errno on failure
7528 */
7529static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7530 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307531 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307532{
7533 struct sir_bpf_set_offload *bpf_set_offload;
7534 QDF_STATUS status;
7535 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307536 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307537
7538 ENTER();
7539
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307540 if (adapter->device_mode == QDF_STA_MODE ||
7541 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7542 if (!hdd_conn_is_connected(
7543 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7544 hdd_err("Not in Connected state!");
7545 return -ENOTSUPP;
7546 }
7547 }
7548
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307549 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7550 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007551 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307552 return -ENOMEM;
7553 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307554
7555 /* Parse and fetch bpf packet size */
7556 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007557 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307558 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307559 goto fail;
7560 }
7561 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7562
7563 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007564 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307565 goto post_sme;
7566 }
7567
7568 /* Parse and fetch bpf program */
7569 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007570 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307571 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307572 goto fail;
7573 }
7574
7575 prog_len = nla_len(tb[BPF_PROGRAM]);
7576 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307577
7578 if (bpf_set_offload->program == NULL) {
7579 hdd_err("qdf_mem_malloc failed for bpf offload program");
7580 ret = -ENOMEM;
7581 goto fail;
7582 }
7583
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307584 bpf_set_offload->current_length = prog_len;
7585 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307586 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307587
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007588 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007589 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307590 bpf_set_offload->program, prog_len);
7591
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307592 /* Parse and fetch filter Id */
7593 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007594 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307595 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307596 goto fail;
7597 }
7598 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7599
7600 /* Parse and fetch current offset */
7601 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007602 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307603 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307604 goto fail;
7605 }
7606 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7607
7608post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007609 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 +05307610 bpf_set_offload->session_id,
7611 bpf_set_offload->version,
7612 bpf_set_offload->filter_id,
7613 bpf_set_offload->total_length,
7614 bpf_set_offload->current_length,
7615 bpf_set_offload->current_offset);
7616
7617 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7618 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007619 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307620 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307621 goto fail;
7622 }
7623 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307624
7625fail:
7626 if (bpf_set_offload->current_length)
7627 qdf_mem_free(bpf_set_offload->program);
7628 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307629 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307630}
7631
7632/**
7633 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7634 * @wiphy: wiphy structure pointer
7635 * @wdev: Wireless device structure pointer
7636 * @data: Pointer to the data received
7637 * @data_len: Length of @data
7638 *
7639 * Return: 0 on success; errno on failure
7640 */
7641static int
7642__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7643 struct wireless_dev *wdev,
7644 const void *data, int data_len)
7645{
7646 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7647 struct net_device *dev = wdev->netdev;
7648 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7649 struct nlattr *tb[BPF_MAX + 1];
7650 int ret_val, packet_filter_subcmd;
7651
7652 ENTER();
7653
7654 ret_val = wlan_hdd_validate_context(hdd_ctx);
7655 if (ret_val)
7656 return ret_val;
7657
7658 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007659 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307660 return -EINVAL;
7661 }
7662
7663 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007664 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307665 return -ENOTSUPP;
7666 }
7667
7668 if (nla_parse(tb, BPF_MAX, data, data_len,
7669 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007670 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307671 return -EINVAL;
7672 }
7673
7674 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007675 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307676 return -EINVAL;
7677 }
7678
7679 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7680
7681 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7682 return hdd_get_bpf_offload(hdd_ctx);
7683 else
7684 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307685 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307686}
7687
7688/**
7689 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7690 * @wiphy: wiphy structure pointer
7691 * @wdev: Wireless device structure pointer
7692 * @data: Pointer to the data received
7693 * @data_len: Length of @data
7694 *
7695 * Return: 0 on success; errno on failure
7696 */
7697
7698static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7699 struct wireless_dev *wdev,
7700 const void *data, int data_len)
7701{
7702 int ret;
7703
7704 cds_ssr_protect(__func__);
7705 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7706 cds_ssr_unprotect(__func__);
7707
7708 return ret;
7709}
7710
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307711/**
7712 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7713 * @pre_cac_adapter: AP adapter used for pre cac
7714 * @status: Status (true or false)
7715 * @handle: Global handle
7716 *
7717 * Sets the status of pre cac i.e., whether the pre cac is active or not
7718 *
7719 * Return: Zero on success, non-zero on failure
7720 */
7721static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7722 bool status, tHalHandle handle)
7723{
7724 QDF_STATUS ret;
7725
7726 ret = wlan_sap_set_pre_cac_status(
7727 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7728 if (QDF_IS_STATUS_ERROR(ret))
7729 return -EINVAL;
7730
7731 return 0;
7732}
7733
7734/**
7735 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7736 * @ap_adapter: AP adapter
7737 * @chan_before_pre_cac: Channel
7738 *
7739 * Saves the channel which the AP was beaconing on before moving to the pre
7740 * cac channel. If radar is detected on the pre cac channel, this saved
7741 * channel will be used for AP operations.
7742 *
7743 * Return: Zero on success, non-zero on failure
7744 */
7745static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7746 uint8_t chan_before_pre_cac)
7747{
7748 QDF_STATUS ret;
7749
7750 ret = wlan_sap_set_chan_before_pre_cac(
7751 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7752 if (QDF_IS_STATUS_ERROR(ret))
7753 return -EINVAL;
7754
7755 return 0;
7756}
7757
7758/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307759 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7760 * are in nol list from provided channel list
7761 * @adapter: AP adapter
7762 * @channel_count: channel count
7763 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307764 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307765 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307766 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307767static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7768 uint32_t *channel_count,
7769 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307770{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307771 uint8_t i, j;
7772 uint32_t nol_len = 0;
7773 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7774 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7775 uint32_t chan_count;
7776 bool found;
7777 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307778
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307779 if (!hdd_ctx) {
7780 hdd_err("hdd ctx not found");
7781 *channel_count = 0;
7782 return;
7783 }
7784
7785 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7786 hdd_err("invalid channel count %d", *channel_count);
7787 return;
7788 }
7789
7790 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7791 if (nol_len == 0)
7792 return;
7793
7794 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7795 chan_count = *channel_count;
7796 qdf_mem_zero(channel_list, chan_count);
7797 *channel_count = 0;
7798
7799 for (i = 0 ; i < chan_count; i++) {
7800 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7801 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7802 continue;
7803 found = false;
7804 for (j = 0; j < nol_len; j++) {
7805 if (tmp_chan_list[i] == nol[j]) {
7806 found = true;
7807 hdd_notice("skipped channel %d due to nol",
7808 nol[j]);
7809 break;
7810 }
7811 }
7812 if (!found) {
7813 channel_list[*channel_count] = tmp_chan_list[i];
7814 *channel_count = *channel_count + 1;
7815 }
7816 }
7817}
7818
7819int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7820 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307821 uint8_t *channel_list,
7822 eCsrBand band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307823{
7824 tsap_Config_t *sap_config;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307825 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7826 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7827 uint32_t chan_count;
7828 uint8_t i;
7829 QDF_STATUS status;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307830
7831 sap_config = &adapter->sessionCtx.ap.sapConfig;
7832
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307833 status =
7834 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7835 tmp_chan_list,
7836 &chan_count);
7837 if (QDF_IS_STATUS_ERROR(status)) {
7838 hdd_err("Failed to get channel list");
7839 return -EINVAL;
7840 }
7841 for (i = 0; i < chan_count; i++) {
7842 if (*channel_count < QDF_MAX_NUM_CHAN) {
7843 if ((eCSR_BAND_24 == band) &&
7844 (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
7845 channel_list[*channel_count] = tmp_chan_list[i];
7846 *channel_count += 1;
7847 } else if ((eCSR_BAND_5G == band) &&
7848 (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
7849 channel_list[*channel_count] = tmp_chan_list[i];
7850 *channel_count += 1;
7851 }
7852 } else {
7853 break;
7854 }
7855 }
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307856 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307857 if (*channel_count == 0) {
7858 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307859 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307860 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307861
7862 return 0;
7863}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307864
7865/**
7866 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7867 * @hdd_ctx: HDD context
7868 * @ap_adapter: AP adapter
7869 * @channel: Channel requested by userspace
7870 * @pre_cac_chan: Pointer to the pre CAC channel
7871 *
7872 * Validates the channel provided by userspace. If user provided channel 0,
7873 * a valid outdoor channel must be selected from the regulatory channel.
7874 *
7875 * Return: Zero on success and non zero value on error
7876 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007877static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7878 hdd_adapter_t *ap_adapter,
7879 uint8_t channel,
7880 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307881{
7882 uint32_t i, j;
7883 QDF_STATUS status;
7884 int ret;
7885 uint8_t nol[QDF_MAX_NUM_CHAN];
7886 uint32_t nol_len = 0, weight_len = 0;
7887 bool found;
7888 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7889 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7890 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7891
7892 if (0 == channel) {
7893 /* Channel is not obtained from PCL because PCL may not have
7894 * the entire channel list. For example: if SAP is up on
7895 * channel 6 and PCL is queried for the next SAP interface,
7896 * if SCC is preferred, the PCL will contain only the channel
7897 * 6. But, we are in need of a DFS channel. So, going with the
7898 * first channel from the valid channel list.
7899 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007900 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7901 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307902 if (QDF_IS_STATUS_ERROR(status)) {
7903 hdd_err("Failed to get channel list");
7904 return -EINVAL;
7905 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007906 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307907 pcl_weights, weight_len);
7908 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7909 for (i = 0; i < len; i++) {
7910 found = false;
7911 for (j = 0; j < nol_len; j++) {
7912 if (channel_list[i] == nol[j]) {
7913 found = true;
7914 break;
7915 }
7916 }
7917 if (found)
7918 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007919 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7920 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307921 *pre_cac_chan = channel_list[i];
7922 break;
7923 }
7924 }
7925 if (*pre_cac_chan == 0) {
7926 hdd_err("unable to find outdoor channel");
7927 return -EINVAL;
7928 }
7929 } else {
7930 /* Only when driver selects a channel, check is done for
7931 * unnsafe and NOL channels. When user provides a fixed channel
7932 * the user is expected to take care of this.
7933 */
7934 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007935 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307936 hdd_err("Invalid channel for pre cac:%d", channel);
7937 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307938 }
Jeff Johnson68755312017-02-10 11:46:55 -08007939
7940 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307941 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007942 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307943 return 0;
7944}
7945
7946/**
7947 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7948 * @channel: Channel option provided by userspace
7949 *
7950 * Sets the driver to the required hardware mode and start an adapater for
7951 * pre CAC which will mimic an AP.
7952 *
7953 * Return: Zero on success, non-zero value on error
7954 */
7955int wlan_hdd_request_pre_cac(uint8_t channel)
7956{
Krunal Sonib37bb352016-12-20 14:12:21 -08007957 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307958 hdd_context_t *hdd_ctx;
7959 int ret;
7960 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7961 hdd_ap_ctx_t *hdd_ap_ctx;
7962 QDF_STATUS status;
7963 struct wiphy *wiphy;
7964 struct net_device *dev;
7965 struct cfg80211_chan_def chandef;
7966 enum nl80211_channel_type channel_type;
7967 uint32_t freq;
7968 struct ieee80211_channel *chan;
7969 tHalHandle handle;
7970 bool val;
7971
7972 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7973 if (0 != wlan_hdd_validate_context(hdd_ctx))
7974 return -EINVAL;
7975
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007976 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307977 hdd_err("pre cac not allowed in concurrency");
7978 return -EINVAL;
7979 }
7980
7981 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7982 if (!ap_adapter) {
7983 hdd_err("unable to get SAP adapter");
7984 return -EINVAL;
7985 }
7986
7987 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7988 if (!handle) {
7989 hdd_err("Invalid handle");
7990 return -EINVAL;
7991 }
7992
7993 val = wlan_sap_is_pre_cac_active(handle);
7994 if (val) {
7995 hdd_err("pre cac is already in progress");
7996 return -EINVAL;
7997 }
7998
7999 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8000 if (!hdd_ap_ctx) {
8001 hdd_err("SAP context is NULL");
8002 return -EINVAL;
8003 }
8004
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008005 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
8006 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308007 hdd_err("SAP is already on DFS channel:%d",
8008 hdd_ap_ctx->operatingChannel);
8009 return -EINVAL;
8010 }
8011
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008012 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308013 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
8014 hdd_ap_ctx->operatingChannel);
8015 return -EINVAL;
8016 }
8017
Krunal Sonib37bb352016-12-20 14:12:21 -08008018 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
8019 if (!mac_addr) {
8020 hdd_err("can't add virtual intf: Not getting valid mac addr");
8021 return -EINVAL;
8022 }
8023
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008024 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308025
8026 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
8027 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08008028 if (ret != 0) {
8029 hdd_err("can't validate pre-cac channel");
8030 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308031 }
8032
8033 hdd_debug("starting pre cac SAP adapter");
8034
8035 /* Starting a SAP adapter:
8036 * Instead of opening an adapter, we could just do a SME open session
8037 * for AP type. But, start BSS would still need an adapter.
8038 * So, this option is not taken.
8039 *
8040 * hdd open adapter is going to register this precac interface with
8041 * user space. This interface though exposed to user space will be in
8042 * DOWN state. Consideration was done to avoid this registration to the
8043 * user space. But, as part of SAP operations multiple events are sent
8044 * to user space. Some of these events received from unregistered
8045 * interface was causing crashes. So, retaining the registration.
8046 *
8047 * So, this interface would remain registered and will remain in DOWN
8048 * state for the CAC duration. We will add notes in the feature
8049 * announcement to not use this temporary interface for any activity
8050 * from user space.
8051 */
8052 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08008053 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308054 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308055 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08008056 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308057 }
8058
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308059 /*
8060 * This interface is internally created by the driver. So, no interface
8061 * up comes for this interface from user space and hence starting
8062 * the adapter internally.
8063 */
8064 if (hdd_start_adapter(pre_cac_adapter)) {
8065 hdd_err("error starting the pre cac adapter");
8066 goto close_pre_cac_adapter;
8067 }
8068
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308069 hdd_debug("preparing for start ap/bss on the pre cac adapter");
8070
8071 wiphy = hdd_ctx->wiphy;
8072 dev = pre_cac_adapter->dev;
8073
8074 /* Since this is only a dummy interface lets us use the IEs from the
8075 * other active SAP interface. In regular scenarios, these IEs would
8076 * come from the user space entity
8077 */
8078 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
8079 sizeof(*ap_adapter->sessionCtx.ap.beacon));
8080 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
8081 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308082 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308083 }
8084 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
8085 ap_adapter->sessionCtx.ap.beacon,
8086 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
8087 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
8088 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
8089 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
8090 ap_adapter->sessionCtx.ap.sapConfig.authType;
8091
8092 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
8093 * to operate on the same bandwidth as that of the 2.4GHz operations.
8094 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
8095 */
8096 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
8097 case CH_WIDTH_20MHZ:
8098 channel_type = NL80211_CHAN_HT20;
8099 break;
8100 case CH_WIDTH_40MHZ:
8101 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
8102 ap_adapter->sessionCtx.ap.sapConfig.channel)
8103 channel_type = NL80211_CHAN_HT40PLUS;
8104 else
8105 channel_type = NL80211_CHAN_HT40MINUS;
8106 break;
8107 default:
8108 channel_type = NL80211_CHAN_NO_HT;
8109 break;
8110 }
8111
8112 freq = cds_chan_to_freq(pre_cac_chan);
8113 chan = __ieee80211_get_channel(wiphy, freq);
8114 if (!chan) {
8115 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308116 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308117 }
8118
8119 cfg80211_chandef_create(&chandef, chan, channel_type);
8120
8121 hdd_debug("orig width:%d channel_type:%d freq:%d",
8122 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
8123 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08008124 /*
8125 * Doing update after opening and starting pre-cac adapter will make
8126 * sure that driver won't do hardware mode change if there are any
8127 * initial hick-ups or issues in pre-cac adapter's configuration.
8128 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
8129 * connection update should result in DBS mode
8130 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008131 status = policy_mgr_update_and_wait_for_connection_update(
8132 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08008133 ap_adapter->sessionId,
8134 pre_cac_chan,
8135 SIR_UPDATE_REASON_PRE_CAC);
8136 if (QDF_IS_STATUS_ERROR(status)) {
8137 hdd_err("error in moving to DBS mode");
8138 goto stop_close_pre_cac_adapter;
8139 }
8140
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308141
8142 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
8143 if (0 != ret) {
8144 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308145 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308146 }
8147
8148 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
8149 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08008150 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308151 if (QDF_IS_STATUS_ERROR(status)) {
8152 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308153 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308154 }
8155
8156 /*
8157 * The pre cac status is set here. But, it would not be reset explicitly
8158 * anywhere, since after the pre cac success/failure, the pre cac
8159 * adapter itself would be removed.
8160 */
8161 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
8162 if (0 != ret) {
8163 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308164 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308165 }
8166
8167 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
8168 hdd_ap_ctx->operatingChannel);
8169 if (0 != ret) {
8170 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308171 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308172 }
8173
8174 ap_adapter->pre_cac_chan = pre_cac_chan;
8175
8176 return 0;
8177
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308178stop_close_pre_cac_adapter:
8179 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308180 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
8181 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308182close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308183 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08008184release_intf_addr_and_return_failure:
8185 /*
8186 * Release the interface address as the adapter
8187 * failed to start, if you don't release then next
8188 * adapter which is trying to come wouldn't get valid
8189 * mac address. Remember we have limited pool of mac addresses
8190 */
8191 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308192 return -EINVAL;
8193}
8194
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308195static const struct nla_policy
8196wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
8197 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
8198};
8199
Agrawal Ashish65634612016-08-18 13:24:32 +05308200static const struct nla_policy
8201wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
8202 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
8203 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
8204};
8205
8206/**
8207 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
8208 * @wiphy: Pointer to wireless phy
8209 * @wdev: Pointer to wireless device
8210 * @data: Pointer to data
8211 * @data_len: Length of @data
8212 *
8213 * This function parses the incoming NL vendor command data attributes and
8214 * updates the SAP context about channel_hint and DFS mode.
8215 * If channel_hint is set, SAP will choose that channel
8216 * as operating channel.
8217 *
8218 * If DFS mode is enabled, driver will include DFS channels
8219 * in ACS else driver will skip DFS channels.
8220 *
8221 * Return: 0 on success, negative errno on failure
8222 */
8223static int
8224__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8225 struct wireless_dev *wdev,
8226 const void *data, int data_len)
8227{
8228 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8229 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
8230 int ret;
8231 struct acs_dfs_policy *acs_policy;
8232 int mode = DFS_MODE_NONE;
8233 int channel_hint = 0;
8234
8235 ENTER_DEV(wdev->netdev);
8236
8237 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8238 hdd_err("Command not allowed in FTM mode");
8239 return -EINVAL;
8240 }
8241
8242 ret = wlan_hdd_validate_context(hdd_ctx);
8243 if (0 != ret)
8244 return ret;
8245
8246 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
8247 data, data_len,
8248 wlan_hdd_set_acs_dfs_config_policy)) {
8249 hdd_err("invalid attr");
8250 return -EINVAL;
8251 }
8252
8253 acs_policy = &hdd_ctx->acs_policy;
8254 /*
8255 * SCM sends this attribute to restrict SAP from choosing
8256 * DFS channels from ACS.
8257 */
8258 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
8259 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
8260
8261 if (!IS_DFS_MODE_VALID(mode)) {
8262 hdd_err("attr acs dfs mode is not valid");
8263 return -EINVAL;
8264 }
8265 acs_policy->acs_dfs_mode = mode;
8266
8267 /*
8268 * SCM sends this attribute to provide an active channel,
8269 * to skip redundant ACS between drivers, and save driver start up time
8270 */
8271 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
8272 channel_hint = nla_get_u8(
8273 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
8274
8275 if (!IS_CHANNEL_VALID(channel_hint)) {
8276 hdd_err("acs channel is not valid");
8277 return -EINVAL;
8278 }
8279 acs_policy->acs_channel = channel_hint;
8280
8281 return 0;
8282}
8283
8284/**
8285 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
8286 * @wiphy: wiphy structure pointer
8287 * @wdev: Wireless device structure pointer
8288 * @data: Pointer to the data received
8289 * @data_len: Length of @data
8290 *
8291 * This function parses the incoming NL vendor command data attributes and
8292 * updates the SAP context about channel_hint and DFS mode.
8293 *
8294 * Return: 0 on success; errno on failure
8295 */
8296static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8297 struct wireless_dev *wdev,
8298 const void *data, int data_len)
8299{
8300 int ret;
8301
8302 cds_ssr_protect(__func__);
8303 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
8304 cds_ssr_unprotect(__func__);
8305
8306 return ret;
8307}
8308
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308309/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308310 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
8311 * @mode : cfg80211 dfs mode
8312 *
8313 * Return: return csr sta roam dfs mode else return NONE
8314 */
8315static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
8316 enum dfs_mode mode)
8317{
8318 switch (mode) {
8319 case DFS_MODE_ENABLE:
8320 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
8321 break;
8322 case DFS_MODE_DISABLE:
8323 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
8324 break;
8325 case DFS_MODE_DEPRIORITIZE:
8326 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
8327 break;
8328 default:
8329 hdd_err("STA Roam policy dfs mode is NONE");
8330 return CSR_STA_ROAM_POLICY_NONE;
8331 }
8332}
8333
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308334/*
8335 * hdd_get_sap_operating_band: Get current operating channel
8336 * for sap.
8337 * @hdd_ctx: hdd context
8338 *
8339 * Return : Corresponding band for SAP operating channel
8340 */
8341uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
8342{
8343 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8344 QDF_STATUS status;
8345 hdd_adapter_t *adapter;
8346 uint8_t operating_channel = 0;
8347 uint8_t sap_operating_band = 0;
8348 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8349 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8350 adapter = adapter_node->pAdapter;
8351
8352 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
8353 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8354 &next);
8355 adapter_node = next;
8356 continue;
8357 }
8358 operating_channel = adapter->sessionCtx.ap.operatingChannel;
8359 if (IS_24G_CH(operating_channel))
8360 sap_operating_band = eCSR_BAND_24;
8361 else if (IS_5G_CH(operating_channel))
8362 sap_operating_band = eCSR_BAND_5G;
8363 else
8364 sap_operating_band = eCSR_BAND_ALL;
8365 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8366 &next);
bings373b99b2017-01-23 10:35:08 +08008367 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308368 }
8369 return sap_operating_band;
8370}
8371
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308372static const struct nla_policy
8373wlan_hdd_set_sta_roam_config_policy[
8374QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
8375 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
8376 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
8377};
8378
8379/**
8380 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
8381 * for station connection or roaming.
8382 * @wiphy: Pointer to wireless phy
8383 * @wdev: Pointer to wireless device
8384 * @data: Pointer to data
8385 * @data_len: Length of @data
8386 *
8387 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8388 * channels needs to be skipped in scanning or not.
8389 * If dfs_mode is disabled, driver will not scan DFS channels.
8390 * If skip_unsafe_channels is set, driver will skip unsafe channels
8391 * in Scanning.
8392 *
8393 * Return: 0 on success, negative errno on failure
8394 */
8395static int
8396__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8397 struct wireless_dev *wdev,
8398 const void *data, int data_len)
8399{
8400 struct net_device *dev = wdev->netdev;
8401 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8402 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8403 struct nlattr *tb[
8404 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8405 int ret;
8406 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8407 enum dfs_mode mode = DFS_MODE_NONE;
8408 bool skip_unsafe_channels = false;
8409 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308410 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308411
8412 ENTER_DEV(dev);
8413
8414 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8415 hdd_err("Command not allowed in FTM mode");
8416 return -EINVAL;
8417 }
8418
8419 ret = wlan_hdd_validate_context(hdd_ctx);
8420 if (0 != ret)
8421 return ret;
8422 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8423 data, data_len,
8424 wlan_hdd_set_sta_roam_config_policy)) {
8425 hdd_err("invalid attr");
8426 return -EINVAL;
8427 }
8428 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8429 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8430 if (!IS_DFS_MODE_VALID(mode)) {
8431 hdd_err("attr sta roam dfs mode policy is not valid");
8432 return -EINVAL;
8433 }
8434
8435 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8436
8437 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8438 skip_unsafe_channels = nla_get_u8(
8439 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308440 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308441 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308442 skip_unsafe_channels, adapter->sessionId,
8443 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308444
8445 if (!QDF_IS_STATUS_SUCCESS(status)) {
8446 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8447 return -EINVAL;
8448 }
8449 return 0;
8450}
8451
8452/**
8453 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8454 * connection and roaming for station.
8455 * @wiphy: wiphy structure pointer
8456 * @wdev: Wireless device structure pointer
8457 * @data: Pointer to the data received
8458 * @data_len: Length of @data
8459 *
8460 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8461 * channels needs to be skipped in scanning or not.
8462 * If dfs_mode is disabled, driver will not scan DFS channels.
8463 * If skip_unsafe_channels is set, driver will skip unsafe channels
8464 * in Scanning.
8465 * Return: 0 on success; errno on failure
8466 */
8467static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8468 struct wireless_dev *wdev,
8469 const void *data, int data_len)
8470{
8471 int ret;
8472
8473 cds_ssr_protect(__func__);
8474 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
8475 cds_ssr_unprotect(__func__);
8476
8477 return ret;
8478}
8479
Agrawal Ashish467dde42016-09-08 18:44:22 +05308480#ifdef FEATURE_WLAN_CH_AVOID
8481/**
8482 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8483 * is on unsafe channel.
8484 * @wiphy: wiphy structure pointer
8485 * @wdev: Wireless device structure pointer
8486 * @data: Pointer to the data received
8487 * @data_len: Length of @data
8488 *
8489 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8490 * on any of unsafe channels.
8491 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8492 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8493 *
8494 * Return: 0 on success; errno on failure
8495 */
8496static int
8497__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8498 struct wireless_dev *wdev,
8499 const void *data, int data_len)
8500{
8501 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8502 int ret;
8503 uint16_t unsafe_channel_count;
8504 int unsafe_channel_index;
8505 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8506
8507 ENTER_DEV(wdev->netdev);
8508
8509 if (!qdf_ctx) {
8510 cds_err("qdf_ctx is NULL");
8511 return -EINVAL;
8512 }
8513
8514 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8515 hdd_err("Command not allowed in FTM mode");
8516 return -EINVAL;
8517 }
8518
8519 ret = wlan_hdd_validate_context(hdd_ctx);
8520 if (0 != ret)
8521 return ret;
8522 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8523 &(hdd_ctx->unsafe_channel_count),
8524 sizeof(hdd_ctx->unsafe_channel_list));
8525
8526 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8527 (uint16_t)NUM_CHANNELS);
8528 for (unsafe_channel_index = 0;
8529 unsafe_channel_index < unsafe_channel_count;
8530 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008531 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308532 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8533 }
8534 hdd_unsafe_channel_restart_sap(hdd_ctx);
8535 return 0;
8536}
8537
8538/**
8539 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8540 * is on unsafe channel.
8541 * @wiphy: wiphy structure pointer
8542 * @wdev: Wireless device structure pointer
8543 * @data: Pointer to the data received
8544 * @data_len: Length of @data
8545 *
8546 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8547 * on any of unsafe channels.
8548 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8549 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8550 *
8551 * Return: 0 on success; errno on failure
8552 */
8553static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8554 struct wireless_dev *wdev,
8555 const void *data, int data_len)
8556{
8557 int ret;
8558
8559 cds_ssr_protect(__func__);
8560 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8561 cds_ssr_unprotect(__func__);
8562
8563 return ret;
8564}
8565
8566#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308567/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308568 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8569 * SAP is on unsafe channel.
8570 * @wiphy: wiphy structure pointer
8571 * @wdev: Wireless device structure pointer
8572 * @data: Pointer to the data received
8573 * @data_len: Length of @data
8574 *
8575 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8576 * driver.
8577 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8578 * will initiate restart of sap.
8579 *
8580 * Return: 0 on success; errno on failure
8581 */
8582static int
8583__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8584 struct wireless_dev *wdev,
8585 const void *data, int data_len)
8586{
8587 struct net_device *ndev = wdev->netdev;
8588 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8589 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8590 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8591 uint8_t config_channel = 0;
8592 hdd_ap_ctx_t *ap_ctx;
8593 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308594 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308595
8596 ENTER();
8597
8598 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008599 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308600 return -EINVAL;
8601 }
8602
8603 ret = wlan_hdd_validate_context(hdd_ctx);
8604 if (0 != ret)
8605 return -EINVAL;
8606
8607 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8608 data, data_len,
8609 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008610 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308611 return -EINVAL;
8612 }
8613
8614 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8615 if (!test_bit(SOFTAP_BSS_STARTED,
8616 &hostapd_adapter->event_flags)) {
8617 hdd_err("SAP is not started yet. Restart sap will be invalid");
8618 return -EINVAL;
8619 }
8620
8621 config_channel =
8622 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8623
8624 if (!((IS_24G_CH(config_channel)) ||
8625 (IS_5G_CH(config_channel)))) {
8626 hdd_err("Channel %d is not valid to restart SAP",
8627 config_channel);
8628 return -ENOTSUPP;
8629 }
8630
8631 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8632 ap_ctx->sapConfig.channel = config_channel;
8633 ap_ctx->sapConfig.ch_params.ch_width =
8634 ap_ctx->sapConfig.ch_width_orig;
8635
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008636 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8637 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308638 ap_ctx->sapConfig.sec_ch,
8639 &ap_ctx->sapConfig.ch_params);
8640
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008641 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308642 }
8643
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308644 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8645 uint32_t freq_len, i;
8646 uint32_t *freq;
8647 uint8_t chans[QDF_MAX_NUM_CHAN];
8648
8649 hdd_debug("setting mandatory freq/chan list");
8650
8651 freq_len = nla_len(
8652 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8653 sizeof(uint32_t);
8654
8655 if (freq_len > QDF_MAX_NUM_CHAN) {
8656 hdd_err("insufficient space to hold channels");
8657 return -ENOMEM;
8658 }
8659
8660 freq = nla_data(
8661 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8662
8663 hdd_debug("freq_len=%d", freq_len);
8664
8665 for (i = 0; i < freq_len; i++) {
8666 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8667 hdd_debug("freq[%d]=%d", i, freq[i]);
8668 }
8669
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008670 status = policy_mgr_set_sap_mandatory_channels(
8671 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308672 if (QDF_IS_STATUS_ERROR(status))
8673 return -EINVAL;
8674 }
8675
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308676 return 0;
8677}
8678
8679/**
8680 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8681 * @wiphy: wiphy structure pointer
8682 * @wdev: Wireless device structure pointer
8683 * @data: Pointer to the data received
8684 * @data_len: Length of @data
8685 *
8686 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8687 * driver.
8688 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8689 * will initiate restart of sap.
8690 *
8691 * Return: 0 on success; errno on failure
8692 */
8693static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8694 struct wireless_dev *wdev,
8695 const void *data, int data_len)
8696{
8697 int ret;
8698
8699 cds_ssr_protect(__func__);
8700 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8701 wdev, data, data_len);
8702 cds_ssr_unprotect(__func__);
8703
8704 return ret;
8705}
8706
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308707#undef BPF_INVALID
8708#undef BPF_SET_RESET
8709#undef BPF_VERSION
8710#undef BPF_ID
8711#undef BPF_PACKET_SIZE
8712#undef BPF_CURRENT_OFFSET
8713#undef BPF_PROGRAM
8714#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308715
8716/**
8717 * define short names for the global vendor params
8718 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8719 */
8720#define PARAM_TOTAL_CMD_EVENT_WAKE \
8721 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8722#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8723 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8724#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8725 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8726#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8727 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8728#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8729 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8730#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8731 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8732#define PARAM_TOTAL_RX_DATA_WAKE \
8733 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8734#define PARAM_RX_UNICAST_CNT \
8735 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8736#define PARAM_RX_MULTICAST_CNT \
8737 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8738#define PARAM_RX_BROADCAST_CNT \
8739 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8740#define PARAM_ICMP_PKT \
8741 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8742#define PARAM_ICMP6_PKT \
8743 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8744#define PARAM_ICMP6_RA \
8745 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8746#define PARAM_ICMP6_NA \
8747 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8748#define PARAM_ICMP6_NS \
8749 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8750#define PARAM_ICMP4_RX_MULTICAST_CNT \
8751 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8752#define PARAM_ICMP6_RX_MULTICAST_CNT \
8753 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8754#define PARAM_OTHER_RX_MULTICAST_CNT \
8755 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308756#define PARAM_RSSI_BREACH_CNT \
8757 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8758#define PARAM_LOW_RSSI_CNT \
8759 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8760#define PARAM_GSCAN_CNT \
8761 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8762#define PARAM_PNO_COMPLETE_CNT \
8763 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8764#define PARAM_PNO_MATCH_CNT \
8765 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8766
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308767
8768
8769/**
8770 * hdd_send_wakelock_stats() - API to send wakelock stats
8771 * @ctx: context to be passed to callback
8772 * @data: data passed to callback
8773 *
8774 * This function is used to send wake lock stats to HAL layer
8775 *
8776 * Return: 0 on success, error number otherwise.
8777 */
8778static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8779 const struct sir_wake_lock_stats *data)
8780{
8781 struct sk_buff *skb;
8782 uint32_t nl_buf_len;
8783 uint32_t total_rx_data_wake, rx_multicast_cnt;
8784 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308785 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308786
8787 ENTER();
8788
8789 nl_buf_len = NLMSG_HDRLEN;
8790 nl_buf_len +=
8791 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8792 (NLMSG_HDRLEN + sizeof(uint32_t));
8793
8794 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8795
8796 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008797 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308798 return -ENOMEM;
8799 }
8800
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008801 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308802 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008803 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308804 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008805 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308806 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008807 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308808 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008809 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308810 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008811 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308812 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008813 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308814 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008815 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8816 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308817 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008818 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308819 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008820 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308821 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008822 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308823 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008824 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308825 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008826 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308827 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308828
8829 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308830 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308831
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308832 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308833 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308834
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308835 rx_multicast_cnt =
8836 data->wow_ipv4_mcast_wake_up_count +
8837 ipv6_rx_multicast_addr_cnt;
8838
8839 total_rx_data_wake =
8840 data->wow_ucast_wake_up_count +
8841 data->wow_bcast_wake_up_count +
8842 rx_multicast_cnt;
8843
8844 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8845 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8846 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8847 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8848 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8849 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8850 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8851 total_rx_data_wake) ||
8852 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8853 data->wow_ucast_wake_up_count) ||
8854 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8855 rx_multicast_cnt) ||
8856 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8857 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308858 nla_put_u32(skb, PARAM_ICMP_PKT,
8859 data->wow_icmpv4_count) ||
8860 nla_put_u32(skb, PARAM_ICMP6_PKT,
8861 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308862 nla_put_u32(skb, PARAM_ICMP6_RA,
8863 data->wow_ipv6_mcast_ra_stats) ||
8864 nla_put_u32(skb, PARAM_ICMP6_NA,
8865 data->wow_ipv6_mcast_na_stats) ||
8866 nla_put_u32(skb, PARAM_ICMP6_NS,
8867 data->wow_ipv6_mcast_ns_stats) ||
8868 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8869 data->wow_ipv4_mcast_wake_up_count) ||
8870 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8871 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308872 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8873 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8874 data->wow_rssi_breach_wake_up_count) ||
8875 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8876 data->wow_low_rssi_wake_up_count) ||
8877 nla_put_u32(skb, PARAM_GSCAN_CNT,
8878 data->wow_gscan_wake_up_count) ||
8879 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8880 data->wow_pno_complete_wake_up_count) ||
8881 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8882 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008883 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308884 goto nla_put_failure;
8885 }
8886
8887 cfg80211_vendor_cmd_reply(skb);
8888
8889 EXIT();
8890 return 0;
8891
8892nla_put_failure:
8893 kfree_skb(skb);
8894 return -EINVAL;
8895}
8896
8897/**
8898 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8899 * @wiphy: wiphy pointer
8900 * @wdev: pointer to struct wireless_dev
8901 * @data: pointer to incoming NL vendor data
8902 * @data_len: length of @data
8903 *
8904 * This function parses the incoming NL vendor command data attributes and
8905 * invokes the SME Api and blocks on a completion variable.
8906 * WMA copies required data and invokes callback
8907 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8908 *
8909 * Return: 0 on success; error number otherwise.
8910 */
8911static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8912 struct wireless_dev *wdev,
8913 const void *data,
8914 int data_len)
8915{
8916 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8917 int status, ret;
8918 struct sir_wake_lock_stats wake_lock_stats;
8919 QDF_STATUS qdf_status;
8920
8921 ENTER();
8922
8923 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008924 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308925 return -EINVAL;
8926 }
8927
8928 status = wlan_hdd_validate_context(hdd_ctx);
8929 if (0 != status)
8930 return -EINVAL;
8931
8932 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8933 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008934 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308935 return -EINVAL;
8936 }
8937
8938 ret = hdd_send_wakelock_stats(hdd_ctx,
8939 &wake_lock_stats);
8940 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008941 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308942
8943 EXIT();
8944 return ret;
8945}
8946
8947/**
8948 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8949 * @wiphy: wiphy pointer
8950 * @wdev: pointer to struct wireless_dev
8951 * @data: pointer to incoming NL vendor data
8952 * @data_len: length of @data
8953 *
8954 * This function parses the incoming NL vendor command data attributes and
8955 * invokes the SME Api and blocks on a completion variable.
8956 * WMA copies required data and invokes callback
8957 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8958 *
8959 * Return: 0 on success; error number otherwise.
8960 */
8961static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8962 struct wireless_dev *wdev,
8963 const void *data, int data_len)
8964{
8965 int ret;
8966
8967 cds_ssr_protect(__func__);
8968 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8969 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008970 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308971
8972 return ret;
8973}
8974
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308975/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308976 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8977 * @wiphy: wiphy structure pointer
8978 * @wdev: Wireless device structure pointer
8979 * @data: Pointer to the data received
8980 * @data_len: Length of @data
8981 *
8982 * This function reads wmi max bus size and fill in the skb with
8983 * NL attributes and send up the NL event.
8984 * Return: 0 on success; errno on failure
8985 */
8986static int
8987__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8988 struct wireless_dev *wdev,
8989 const void *data, int data_len)
8990{
8991 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8992 int ret_val;
8993 struct sk_buff *skb;
8994 uint32_t nl_buf_len;
8995
8996 ENTER();
8997
8998 ret_val = wlan_hdd_validate_context(hdd_ctx);
8999 if (ret_val)
9000 return ret_val;
9001
9002 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9003 hdd_err("Command not allowed in FTM mode");
9004 return -EINVAL;
9005 }
9006
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009007 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309008
9009 nl_buf_len = NLMSG_HDRLEN;
9010 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
9011
9012 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
9013 if (!skb) {
9014 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
9015 return -ENOMEM;
9016 }
9017
9018 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
9019 hdd_ctx->wmi_max_len)) {
9020 hdd_err("nla put failure");
9021 goto nla_put_failure;
9022 }
9023
9024 cfg80211_vendor_cmd_reply(skb);
9025
9026 EXIT();
9027
9028 return 0;
9029
9030nla_put_failure:
9031 kfree_skb(skb);
9032 return -EINVAL;
9033}
9034
9035/**
9036 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
9037 * @wiphy: wiphy structure pointer
9038 * @wdev: Wireless device structure pointer
9039 * @data: Pointer to the data received
9040 * @data_len: Length of @data
9041 *
9042 * Return: 0 on success; errno on failure
9043 */
9044static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
9045 struct wireless_dev *wdev,
9046 const void *data, int data_len)
9047{
9048 int ret;
9049
9050 cds_ssr_protect(__func__);
9051 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
9052 cds_ssr_unprotect(__func__);
9053
9054 return ret;
9055}
9056
9057/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309058 *__wlan_hdd_cfg80211_setband() - set band
9059 * @wiphy: Pointer to wireless phy
9060 * @wdev: Pointer to wireless device
9061 * @data: Pointer to data
9062 * @data_len: Length of @data
9063 *
9064 * Return: 0 on success, negative errno on failure
9065 */
9066static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9067 struct wireless_dev *wdev,
9068 const void *data, int data_len)
9069{
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309070 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07009071 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309072 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9073 int ret;
9074 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
9075 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
9076
9077 ENTER();
9078
9079 ret = wlan_hdd_validate_context(hdd_ctx);
9080 if (ret)
9081 return ret;
9082
9083 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
9084 hdd_err(FL("Invalid ATTR"));
9085 return -EINVAL;
9086 }
9087
9088 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
9089 hdd_err(FL("attr SETBAND_VALUE failed"));
9090 return -EINVAL;
9091 }
9092
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07009093 ret = hdd_reg_set_band(dev,
9094 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309095
9096 EXIT();
9097 return ret;
9098}
9099
9100/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309101 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
9102 * @adapter: hdd adapter
9103 * @channel: channel number
9104 *
9105 * return: QDF status based on success or failure
9106 */
9107static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
9108 int channel, int chan_bw)
9109{
9110 if (QDF_STATUS_SUCCESS !=
9111 wlan_hdd_validate_operation_channel(adapter, channel))
9112 return QDF_STATUS_E_FAILURE;
9113 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9114 channel,
9115 PHY_SINGLE_CHANNEL_CENTERED))) {
9116 hdd_notice("channel %d is in nol", channel);
9117 return -EINVAL;
9118 }
9119
9120 if ((wlansap_is_channel_leaking_in_nol(
9121 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9122 channel, chan_bw))) {
9123 hdd_notice("channel %d is leaking in nol", channel);
9124 return -EINVAL;
9125 }
9126
9127 return 0;
9128
9129}
9130
Kapil Gupta8878ad92017-02-13 11:56:04 +05309131static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
9132 tsap_Config_t *sap_config,
9133 struct hdd_vendor_chan_info *channel_list)
9134{
9135 sap_config->channel = channel_list->pri_ch;
9136
9137 sap_config->ch_params.center_freq_seg0 =
9138 channel_list->vht_seg0_center_ch;
9139 sap_config->ch_params.center_freq_seg1 =
9140 channel_list->vht_seg1_center_ch;
9141
9142 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
9143 sap_config->ch_params.ch_width = channel_list->chan_width;
9144 if (sap_config->channel >= 36)
9145 sap_config->ch_width_orig =
9146 hdd_ctx->config->vhtChannelWidth;
9147 else
9148 sap_config->ch_width_orig =
9149 hdd_ctx->config->nChannelBondingMode24GHz ?
9150 eHT_CHANNEL_WIDTH_40MHZ :
9151 eHT_CHANNEL_WIDTH_20MHZ;
9152
9153 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
9154 sap_config->acs_cfg.ch_width = channel_list->chan_width;
9155 sap_config->acs_cfg.vht_seg0_center_ch =
9156 channel_list->vht_seg0_center_ch;
9157 sap_config->acs_cfg.vht_seg1_center_ch =
9158 channel_list->vht_seg1_center_ch;
9159 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
9160}
9161
9162static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
9163 uint8_t channel_cnt,
9164 struct hdd_vendor_chan_info *channel_list)
9165{
9166 tsap_Config_t *sap_config;
9167 hdd_ap_ctx_t *hdd_ap_ctx;
9168 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9169 QDF_STATUS status = QDF_STATUS_SUCCESS;
9170
9171 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
9172 sap_config = &adapter->sessionCtx.ap.sapConfig;
9173
9174 if (QDF_TIMER_STATE_RUNNING ==
9175 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
9176 ap.vendor_acs_timer)) {
9177 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
9178 }
9179
9180 if (channel_list && channel_list->pri_ch == 0) {
9181 /* Check mode, set default channel */
9182 channel_list->pri_ch = 6;
9183 /*
9184 * sap_select_default_oper_chan(hdd_ctx->hHal,
9185 * sap_config->acs_cfg.hw_mode);
9186 */
9187 }
9188
9189 switch (reason) {
9190 /* SAP init case */
9191 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
9192 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
9193 /* Update Hostapd */
9194 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
9195 break;
9196
9197 /* DFS detected on current channel */
9198 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
9199 wlan_sap_update_next_channel(
9200 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9201 channel_list->pri_ch,
9202 channel_list->chan_width);
9203 status = sme_update_new_channel_event(
9204 WLAN_HDD_GET_HAL_CTX(adapter),
9205 adapter->sessionId);
9206 break;
9207
9208 /* LTE coex event on current channel */
9209 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
9210 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
9211 sap_config->acs_cfg.ch_width = channel_list->chan_width;
9212 hdd_ap_ctx->sapConfig.ch_width_orig =
9213 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08009214 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309215 break;
9216
9217 default:
9218 hdd_info("invalid reason for timer invoke");
9219 }
9220 qdf_mem_free(channel_list);
9221 EXIT();
9222 return status;
9223}
9224
9225/**
9226 * Define short name for vendor channel set config
9227 */
9228#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
9229#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
9230#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
9231#define SET_CHAN_PRIMARY_CHANNEL \
9232 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
9233#define SET_CHAN_SECONDARY_CHANNEL \
9234 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
9235#define SET_CHAN_SEG0_CENTER_CHANNEL \
9236 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
9237#define SET_CHAN_SEG1_CENTER_CHANNEL \
9238 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
9239#define SET_CHAN_CHANNEL_WIDTH \
9240 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
9241#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
9242
9243/**
9244 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
9245 * @channel_list: pointer to hdd_vendor_chan_info
9246 * @reason: channel change reason
9247 * @channel_cnt: channel count
9248 * @data: data
9249 * @data_len: data len
9250 *
9251 * Return: 0 on success, negative errno on failure
9252 */
9253static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
9254 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
9255 const void *data, int data_len)
9256{
9257 int rem, i = 0;
9258 struct nlattr *tb[SET_CHAN_MAX + 1];
9259 struct nlattr *tb2[SET_CHAN_MAX + 1];
9260 struct nlattr *curr_attr;
9261 struct hdd_vendor_chan_info *channel_list;
9262
9263 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
9264 hdd_err("Invalid ATTR");
9265 return -EINVAL;
9266 }
9267
9268 if (tb[SET_CHAN_REASON])
9269 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
9270
9271 if (tb[SET_CHAN_CHANNEL_COUNT]) {
9272 *channel_cnt = nla_get_u8(tb[
9273 SET_CHAN_CHANNEL_COUNT]);
9274 hdd_info("channel count %d", *channel_cnt);
9275 }
9276
9277 if (!(*channel_cnt)) {
9278 hdd_err("channel count is %d", *channel_cnt);
9279 return -EINVAL;
9280 }
9281
9282 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
9283 (*channel_cnt));
9284
9285 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
9286 if (nla_parse(tb2,
9287 SET_CHAN_MAX,
9288 nla_data(curr_attr), nla_len(curr_attr),
9289 NULL)) {
9290 hdd_err("nla_parse failed");
9291 return -EINVAL;
9292 }
9293 /* Parse and Fetch allowed SSID list*/
9294 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
9295 channel_list[i].pri_ch =
9296 nla_get_u8(
9297 tb2[SET_CHAN_PRIMARY_CHANNEL]);
9298 }
9299 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
9300 channel_list[i].ht_sec_ch =
9301 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
9302 }
9303 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
9304 channel_list[i].vht_seg0_center_ch =
9305 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
9306 }
9307 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
9308 channel_list[i].vht_seg1_center_ch =
9309 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
9310 }
9311 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
9312 channel_list[i].chan_width =
9313 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
9314 }
9315 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
9316 i, channel_list[i].pri_ch,
9317 channel_list[i].ht_sec_ch,
9318 channel_list[i].vht_seg0_center_ch,
9319 channel_list[i].vht_seg1_center_ch,
9320 channel_list[i].chan_width);
9321 i++;
9322 if (i > *channel_cnt)
9323 break;
9324 }
9325 *chan_list_ptr = channel_list;
9326
9327 return 0;
9328}
9329
9330/**
9331 * Undef short names for vendor set channel configuration
9332 */
9333#undef SET_CHAN_REASON
9334#undef SET_CHAN_CHANNEL_COUNT
9335#undef SET_CHAN_CHAN_LIST
9336#undef SET_CHAN_PRIMARY_CHANNEL
9337#undef SET_CHAN_SECONDARY_CHANNEL
9338#undef SET_CHAN_SEG0_CENTER_CHANNEL
9339#undef SET_CHAN_SEG1_CENTER_CHANNEL
9340#undef SET_CHAN_CHANNEL_WIDTH
9341#undef SET_CHAN_MAX
9342
9343/**
9344 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9345 * @wiphy: Pointer to wireless phy
9346 * @wdev: Pointer to wireless device
9347 * @data: Pointer to data
9348 * @data_len: Length of @data
9349 *
9350 * Return: 0 on success, negative errno on failure
9351 */
9352static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9353 struct wireless_dev *wdev,
9354 const void *data, int data_len)
9355{
9356 int ret_val;
9357 QDF_STATUS qdf_status;
9358 uint8_t channel_cnt = 0, reason = -1;
9359 struct hdd_vendor_chan_info *channel_list = NULL;
9360 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
9361 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9362
9363 ENTER();
9364
9365 ret_val = wlan_hdd_validate_context(hdd_ctx);
9366 if (ret_val)
9367 return ret_val;
9368
9369 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9370 hdd_err("Command not allowed in FTM mode");
9371 return -EINVAL;
9372 }
9373
9374 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
9375 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
9376 else {
9377 hdd_err("already timeout happened for acs");
9378 return -EINVAL;
9379 }
9380
9381 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
9382 &channel_cnt, data, data_len);
9383 if (ret_val)
9384 return ret_val;
9385
9386 /* Validate channel to be set */
9387 while (channel_cnt && channel_list) {
9388 qdf_status = wlan_hdd_validate_acs_channel(adapter,
9389 channel_list->pri_ch,
9390 channel_list->chan_width);
9391 if (qdf_status == QDF_STATUS_SUCCESS)
9392 break;
9393 channel_cnt--;
9394 channel_list++;
9395 }
9396 if ((channel_cnt <= 0) || !channel_list) {
9397 hdd_err("no available channel/chanlist %p", channel_list);
9398 return -EINVAL;
9399 }
9400
9401 qdf_status = hdd_update_acs_channel(adapter, reason,
9402 channel_cnt, channel_list);
9403 return qdf_status_to_os_return(qdf_status);
9404}
9405
9406/**
9407 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
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 * Return: 0 on success, negative errno on failure
9414 */
9415static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9416 struct wireless_dev *wdev,
9417 const void *data, int data_len)
9418{
9419 int ret;
9420
9421 cds_ssr_protect(__func__);
9422 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
9423 data_len);
9424 cds_ssr_protect(__func__);
9425
9426 return ret;
9427}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309428
9429/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309430 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9431 * @wiphy: wiphy structure pointer
9432 * @wdev: Wireless device structure pointer
9433 * @data: Pointer to the data received
9434 * @data_len: Length of @data
9435 *
9436 * Return: 0 on success; errno on failure
9437 */
9438static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9439 struct wireless_dev *wdev,
9440 const void *data, int data_len)
9441{
9442 int ret;
9443
9444 cds_ssr_protect(__func__);
9445 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9446 cds_ssr_unprotect(__func__);
9447
9448 return ret;
9449}
9450
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009451/**
9452 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9453 * @nl80211_value: Vendor command attribute value
9454 * @wmi_value: Pointer to return converted WMI return value
9455 *
9456 * Convert NL80211 vendor command value for SAR limit set to WMI value
9457 * Return: 0 on success, -1 on invalid value
9458 */
9459static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9460 u32 *wmi_value)
9461{
9462 int ret = 0;
9463
9464 switch (nl80211_value) {
9465 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9466 *wmi_value = WMI_SAR_FEATURE_OFF;
9467 break;
9468 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9469 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9470 break;
9471 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9472 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9473 break;
9474 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9475 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9476 break;
9477 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9478 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9479 break;
9480 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9481 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9482 break;
9483 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9484 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9485 break;
9486 default:
9487 ret = -1;
9488 }
9489 return ret;
9490}
9491
9492/**
9493 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9494 * @nl80211_value: Vendor command attribute value
9495 * @wmi_value: Pointer to return converted WMI return value
9496 *
9497 * Convert NL80211 vendor command value for SAR BAND to WMI value
9498 * Return: 0 on success, -1 on invalid value
9499 */
9500static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9501{
9502 int ret = 0;
9503
9504 switch (nl80211_value) {
9505 case NL80211_BAND_2GHZ:
9506 *wmi_value = WMI_SAR_2G_ID;
9507 break;
9508 case NL80211_BAND_5GHZ:
9509 *wmi_value = WMI_SAR_5G_ID;
9510 break;
9511 default:
9512 ret = -1;
9513 }
9514 return ret;
9515}
9516
9517/**
9518 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9519 * @nl80211_value: Vendor command attribute value
9520 * @wmi_value: Pointer to return converted WMI return value
9521 *
9522 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9523 * Return: 0 on success, -1 on invalid value
9524 */
9525static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9526 u32 *wmi_value)
9527{
9528 int ret = 0;
9529
9530 switch (nl80211_value) {
9531 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9532 *wmi_value = WMI_SAR_MOD_CCK;
9533 break;
9534 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9535 *wmi_value = WMI_SAR_MOD_OFDM;
9536 break;
9537 default:
9538 ret = -1;
9539 }
9540 return ret;
9541}
9542
9543
9544/**
9545 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9546 * @wiphy: Pointer to wireless phy
9547 * @wdev: Pointer to wireless device
9548 * @data: Pointer to data
9549 * @data_len: Length of @data
9550 *
9551 * This function is used to setup Specific Absorption Rate limit specs.
9552 *
9553 * Return: 0 on success, negative errno on failure
9554 */
9555static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9556 struct wireless_dev *wdev,
9557 const void *data, int data_len)
9558{
9559 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9560 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9561 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9562 *sar_spec_list;
9563 struct sar_limit_cmd_params sar_limit_cmd = {0};
9564 int ret = -EINVAL, i = 0, rem = 0;
9565
9566 ENTER();
9567
9568 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9569 hdd_err("Command not allowed in FTM mode");
9570 return -EPERM;
9571 }
9572
9573 if (wlan_hdd_validate_context(hdd_ctx))
9574 return -EINVAL;
9575
9576 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9577 data, data_len, NULL)) {
9578 hdd_err("Invalid SAR attributes");
9579 return -EINVAL;
9580 }
9581
9582 /* Vendor command manadates all SAR Specs in single call */
9583 sar_limit_cmd.commit_limits = 1;
9584 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9585 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9586 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9587 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9588 &sar_limit_cmd.sar_enable) < 0) {
9589 hdd_err("Invalid SAR Enable attr");
9590 goto fail;
9591 }
9592 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009593 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009594
9595 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9596 sar_limit_cmd.num_limit_rows = nla_get_u32(
9597 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009598 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009599 sar_limit_cmd.num_limit_rows);
9600 }
9601 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9602 hdd_err("SAR Spec list exceed supported size");
9603 goto fail;
9604 }
9605 if (sar_limit_cmd.num_limit_rows == 0)
9606 goto send_sar_limits;
9607 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9608 struct sar_limit_cmd_row) *
9609 sar_limit_cmd.num_limit_rows);
9610 if (!sar_limit_cmd.sar_limit_row_list) {
9611 ret = -ENOMEM;
9612 goto fail;
9613 }
9614 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9615 hdd_err("Invalid SAR SPECs list");
9616 goto fail;
9617 }
9618
9619 nla_for_each_nested(sar_spec_list,
9620 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9621 if (i == sar_limit_cmd.num_limit_rows) {
9622 hdd_warn("SAR Cmd has excess SPECs in list");
9623 break;
9624 }
9625
9626 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9627 nla_data(sar_spec_list), nla_len(sar_spec_list),
9628 NULL)) {
9629 hdd_err("nla_parse failed for SAR Spec list");
9630 goto fail;
9631 }
9632 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9633 if (sar_spec[
9634 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9635 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9636 nla_get_u32(sar_spec[
9637 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9638 } else {
9639 hdd_err("SAR Spec does not have power limit value");
9640 goto fail;
9641 }
9642
9643 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9644 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9645 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9646 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9647 < 0) {
9648 hdd_err("Invalid SAR Band attr");
9649 goto fail;
9650 }
9651 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9652 WMI_SAR_BAND_ID_VALID_MASK;
9653 }
9654 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9655 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9656 nla_get_u32(sar_spec[
9657 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9658 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9659 WMI_SAR_CHAIN_ID_VALID_MASK;
9660 }
9661 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9662 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9663 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9664 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9665 < 0) {
9666 hdd_err("Invalid SAR Modulation attr");
9667 goto fail;
9668 }
9669 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9670 WMI_SAR_MOD_ID_VALID_MASK;
9671 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009672 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009673 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9674 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9675 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9676 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9677 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9678 i++;
9679 }
9680
9681 if (i < sar_limit_cmd.num_limit_rows) {
9682 hdd_warn("SAR Cmd has less SPECs in list");
9683 sar_limit_cmd.num_limit_rows = i;
9684 }
9685
9686send_sar_limits:
9687 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9688 QDF_STATUS_SUCCESS)
9689 ret = 0;
9690fail:
9691 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9692 return ret;
9693}
9694
9695/**
9696 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9697 * @wiphy: Pointer to wireless phy
9698 * @wdev: Pointer to wireless device
9699 * @data: Pointer to data
9700 * @data_len: Length of @data
9701 *
9702 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9703 *
9704 * Return: 0 on success, negative errno on failure
9705 */
9706static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9707 struct wireless_dev *wdev,
9708 const void *data,
9709 int data_len)
9710{
9711 int ret;
9712
9713 cds_ssr_protect(__func__);
9714 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9715 data_len);
9716 cds_ssr_unprotect(__func__);
9717
9718 return ret;
9719}
9720
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309721static const struct
9722nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9723 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9724 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9725 .len = QDF_MAC_ADDR_SIZE},
9726};
9727
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309728void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9729{
9730 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9731 hdd_adapter_t *adapter;
9732
9733 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9734 if (!adapter) {
9735 hdd_err("adapter NULL");
9736 return;
9737 }
9738
9739 adapter->lfr_fw_status.is_disabled = rso_status->status;
9740 complete(&adapter->lfr_fw_status.disable_lfr_event);
9741}
9742
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309743/**
9744 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9745 * @wiphy: Pointer to wireless phy
9746 * @wdev: Pointer to wireless device
9747 * @data: Pointer to data
9748 * @data_len: Length of @data
9749 *
9750 * This function is used to enable/disable roaming using vendor commands
9751 *
9752 * Return: 0 on success, negative errno on failure
9753 */
9754static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9755 struct wireless_dev *wdev,
9756 const void *data, int data_len)
9757{
9758 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9759 struct net_device *dev = wdev->netdev;
9760 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9761 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309762 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309763 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309764 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309765 unsigned long rc;
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309766 hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309767
9768 ENTER_DEV(dev);
9769
9770 ret = wlan_hdd_validate_context(hdd_ctx);
9771 if (0 != ret)
9772 return ret;
9773
9774 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9775 hdd_err("Command not allowed in FTM mode");
9776 return -EINVAL;
9777 }
9778
9779 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9780 qca_wlan_vendor_attr);
9781 if (ret) {
9782 hdd_err("Invalid ATTR");
9783 return -EINVAL;
9784 }
9785
9786 /* Parse and fetch Enable flag */
9787 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9788 hdd_err("attr enable failed");
9789 return -EINVAL;
9790 }
9791
9792 is_fast_roam_enabled = nla_get_u32(
9793 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009794 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009795 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309796
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009797 if (!adapter->fast_roaming_allowed) {
9798 hdd_err("fast roaming not allowed on %s interface",
9799 adapter->dev->name);
9800 return -EINVAL;
9801 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309802 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309803 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309804 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309805 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309806 if (qdf_status != QDF_STATUS_SUCCESS)
9807 hdd_err("sme_config_fast_roaming failed with status=%d",
9808 qdf_status);
9809 ret = qdf_status_to_os_return(qdf_status);
9810
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309811 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
9812 QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9813
9814 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309815 /*
9816 * wait only for LFR disable in fw as LFR enable
9817 * is always success
9818 */
9819 rc = wait_for_completion_timeout(
9820 &adapter->lfr_fw_status.disable_lfr_event,
9821 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9822 if (!rc) {
9823 hdd_err("Timed out waiting for RSO CMD status");
9824 return -ETIMEDOUT;
9825 }
9826
9827 if (!adapter->lfr_fw_status.is_disabled) {
9828 hdd_err("Roam disable attempt in FW fails");
9829 return -EBUSY;
9830 }
9831 }
9832
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309833 EXIT();
9834 return ret;
9835}
9836
9837/**
9838 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9839 * @wiphy: Pointer to wireless phy
9840 * @wdev: Pointer to wireless device
9841 * @data: Pointer to data
9842 * @data_len: Length of @data
9843 *
9844 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9845 *
9846 * Return: 0 on success, negative errno on failure
9847 */
9848static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9849 struct wireless_dev *wdev,
9850 const void *data, int data_len)
9851{
9852 int ret;
9853
9854 cds_ssr_protect(__func__);
9855 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9856 cds_ssr_unprotect(__func__);
9857
9858 return ret;
9859}
9860
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309861
9862void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9863 uint32_t vdev_id)
9864{
9865 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9866 int status;
9867 hdd_adapter_t *adapter = NULL;
9868 hdd_station_ctx_t *hdd_sta_ctx;
9869
9870 status = wlan_hdd_validate_context(hdd_ctx);
9871 if (status != 0)
9872 return;
9873
9874 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9875 if (adapter == NULL) {
9876 hdd_err("vdev_id %d does not exist with host", vdev_id);
9877 return;
9878 }
9879
9880 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9881 hdd_sta_ctx->conn_info.cca = congestion;
9882 hdd_info("congestion:%d", congestion);
9883}
9884
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309885static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9886 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9887 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9888 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9889 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9890};
9891
9892/**
9893 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9894 * @wiphy: Pointer to wireless phy
9895 * @wdev: Pointer to wireless device
9896 * @data: Pointer to data
9897 * @data_len: Length of @data
9898 *
9899 * Return: 0 on success, negative errno on failure
9900 */
9901static int
9902__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9903 struct wireless_dev *wdev,
9904 const void *data,
9905 int data_len)
9906{
9907 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9908 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9909 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9910 struct nlattr *apth;
9911 int rem;
9912 int ret = 1;
9913 int print_idx = -1;
9914 int module_id = -1;
9915 int bit_mask = -1;
9916 int status;
9917
9918 ENTER();
9919
9920 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9921 hdd_err("Command not allowed in FTM mode");
9922 return -EINVAL;
9923 }
9924
9925 ret = wlan_hdd_validate_context(hdd_ctx);
9926 if (ret != 0)
9927 return -EINVAL;
9928
9929 print_idx = qdf_get_pidx();
9930 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9931 hdd_err("Invalid print controle object index");
9932 return -EINVAL;
9933 }
9934
9935 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9936 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9937 hdd_err("Invalid attr");
9938 return -EINVAL;
9939 }
9940
9941 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9942 hdd_err("attr trace level param failed");
9943 return -EINVAL;
9944 }
9945
9946 nla_for_each_nested(apth,
9947 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9948 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9949 nla_data(apth), nla_len(apth), NULL)) {
9950 hdd_err("Invalid attr");
9951 return -EINVAL;
9952 }
9953
9954 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9955 hdd_err("attr Module ID failed");
9956 return -EINVAL;
9957 }
9958 module_id = nla_get_u32
9959 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9960
9961 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9962 hdd_err("attr Verbose mask failed");
9963 return -EINVAL;
9964 }
9965 bit_mask = nla_get_u32
9966 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9967
9968 status = hdd_qdf_trace_enable(module_id, bit_mask);
9969
9970 if (status != 0)
9971 hdd_err("can not set verbose mask %d for the category %d",
9972 bit_mask, module_id);
9973 }
9974
9975 EXIT();
9976 return ret;
9977}
9978
9979/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309980 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9981 * @wiphy: Pointer to wireless phy
9982 * @wdev: Pointer to wireless device
9983 * @data: Pointer to data
9984 * @data_len: Length of @data
9985 *
9986 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9987 *
9988 * Return: 0 on success, negative errno on failure
9989 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309990
9991static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9992 struct wireless_dev *wdev,
9993 const void *data,
9994 int data_len)
9995{
9996 int ret;
9997
9998 cds_ssr_protect(__func__);
9999 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
10000 cds_ssr_unprotect(__func__);
10001
10002 return ret;
10003}
10004
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010005const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
10006 {
10007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10008 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
10009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +053010010 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010011 .doit = is_driver_dfs_capable
10012 },
10013
10014#ifdef WLAN_FEATURE_NAN
10015 {
10016 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10017 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
10018 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10019 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10020 .doit = wlan_hdd_cfg80211_nan_request
10021 },
10022#endif
10023
10024#ifdef WLAN_FEATURE_STATS_EXT
10025 {
10026 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10027 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
10028 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10029 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10030 .doit = wlan_hdd_cfg80211_stats_ext_request
10031 },
10032#endif
10033#ifdef FEATURE_WLAN_EXTSCAN
10034 {
10035 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10036 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
10037 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10038 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10039 .doit = wlan_hdd_cfg80211_extscan_start
10040 },
10041 {
10042 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10043 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
10044 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10045 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10046 .doit = wlan_hdd_cfg80211_extscan_stop
10047 },
10048 {
10049 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10050 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
10051 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
10052 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
10053 },
10054 {
10055 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10056 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
10057 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10058 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10059 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
10060 },
10061 {
10062 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10063 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
10064 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10065 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10066 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
10067 },
10068 {
10069 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10070 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
10071 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10072 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10073 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
10074 },
10075 {
10076 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10077 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
10078 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10079 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10080 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
10081 },
10082 {
10083 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10084 .info.subcmd =
10085 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
10086 .flags =
10087 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
10088 WIPHY_VENDOR_CMD_NEED_RUNNING,
10089 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
10090 },
10091 {
10092 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10093 .info.subcmd =
10094 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
10095 .flags =
10096 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
10097 WIPHY_VENDOR_CMD_NEED_RUNNING,
10098 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
10099 },
10100 {
10101 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10102 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
10103 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10104 WIPHY_VENDOR_CMD_NEED_NETDEV |
10105 WIPHY_VENDOR_CMD_NEED_RUNNING,
10106 .doit = wlan_hdd_cfg80211_set_epno_list
10107 },
10108#endif /* FEATURE_WLAN_EXTSCAN */
10109
10110#ifdef WLAN_FEATURE_LINK_LAYER_STATS
10111 {
10112 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10113 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
10114 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10115 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10116 .doit = wlan_hdd_cfg80211_ll_stats_clear
10117 },
10118
10119 {
10120 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10121 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
10122 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10123 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10124 .doit = wlan_hdd_cfg80211_ll_stats_set
10125 },
10126
10127 {
10128 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10129 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
10130 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10131 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10132 .doit = wlan_hdd_cfg80211_ll_stats_get
10133 },
10134#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
10135#ifdef FEATURE_WLAN_TDLS
10136 {
10137 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10138 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
10139 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10140 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10141 .doit = wlan_hdd_cfg80211_exttdls_enable
10142 },
10143 {
10144 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10145 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
10146 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10147 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10148 .doit = wlan_hdd_cfg80211_exttdls_disable
10149 },
10150 {
10151 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10152 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
10153 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
10154 .doit = wlan_hdd_cfg80211_exttdls_get_status
10155 },
10156#endif
10157 {
10158 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10159 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
10160 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
10161 .doit = wlan_hdd_cfg80211_get_supported_features
10162 },
10163 {
10164 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10165 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010166 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10167 WIPHY_VENDOR_CMD_NEED_NETDEV |
10168 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010169 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
10170 },
10171 {
10172 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10173 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
10174 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +053010175 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010176 },
10177 {
10178 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10179 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
10180 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010181 WIPHY_VENDOR_CMD_NEED_NETDEV |
10182 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
10184 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070010185 {
10186 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10187 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
10188 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010189 WIPHY_VENDOR_CMD_NEED_NETDEV |
10190 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070010191 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
10192 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010193 {
10194 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +053010195 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
10196 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10197 WIPHY_VENDOR_CMD_NEED_NETDEV |
10198 WIPHY_VENDOR_CMD_NEED_RUNNING,
10199 .doit = hdd_cfg80211_get_station_cmd
10200 },
10201 {
10202 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010203 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
10204 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10205 WIPHY_VENDOR_CMD_NEED_NETDEV |
10206 WIPHY_VENDOR_CMD_NEED_RUNNING,
10207 .doit = wlan_hdd_cfg80211_do_acs
10208 },
10209
10210 {
10211 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10212 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
10213 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10214 WIPHY_VENDOR_CMD_NEED_NETDEV,
10215 .doit = wlan_hdd_cfg80211_get_features
10216 },
10217#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10218 {
10219 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10220 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
10221 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10222 WIPHY_VENDOR_CMD_NEED_NETDEV |
10223 WIPHY_VENDOR_CMD_NEED_RUNNING,
10224 .doit = wlan_hdd_cfg80211_keymgmt_set_key
10225 },
10226#endif
10227#ifdef FEATURE_WLAN_EXTSCAN
10228 {
10229 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10230 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
10231 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10232 WIPHY_VENDOR_CMD_NEED_NETDEV |
10233 WIPHY_VENDOR_CMD_NEED_RUNNING,
10234 .doit = wlan_hdd_cfg80211_set_passpoint_list
10235 },
10236 {
10237 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10238 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
10239 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10240 WIPHY_VENDOR_CMD_NEED_NETDEV |
10241 WIPHY_VENDOR_CMD_NEED_RUNNING,
10242 .doit = wlan_hdd_cfg80211_reset_passpoint_list
10243 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010244#endif /* FEATURE_WLAN_EXTSCAN */
10245 {
10246 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10247 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
10248 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10249 WIPHY_VENDOR_CMD_NEED_NETDEV,
10250 .doit = wlan_hdd_cfg80211_get_wifi_info
10251 },
Paul Zhang3a210c52016-12-08 10:18:12 +080010252#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010253 {
10254 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10255 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
10256 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10257 WIPHY_VENDOR_CMD_NEED_NETDEV |
10258 WIPHY_VENDOR_CMD_NEED_RUNNING,
10259 .doit = wlan_hdd_cfg80211_wifi_configuration_set
10260 },
Paul Zhang3a210c52016-12-08 10:18:12 +080010261#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010262 {
10263 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10264 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
10265 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010266 WIPHY_VENDOR_CMD_NEED_NETDEV |
10267 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010268 .doit = wlan_hdd_cfg80211_set_ext_roam_params
10269 },
10270 {
10271 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10272 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
10273 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010274 WIPHY_VENDOR_CMD_NEED_NETDEV |
10275 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010276 .doit = wlan_hdd_cfg80211_wifi_logger_start
10277 },
10278 {
10279 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10280 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
10281 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010282 WIPHY_VENDOR_CMD_NEED_NETDEV |
10283 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010284 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
10285 },
10286 {
10287 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10288 .info.subcmd =
10289 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
10290 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10291 WIPHY_VENDOR_CMD_NEED_NETDEV |
10292 WIPHY_VENDOR_CMD_NEED_RUNNING,
10293 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
10294 },
10295 {
10296 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10297 .info.subcmd =
10298 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
10299 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10300 WIPHY_VENDOR_CMD_NEED_NETDEV |
10301 WIPHY_VENDOR_CMD_NEED_RUNNING,
10302 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
10303 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070010304#ifdef WLAN_FEATURE_TSF
10305 {
10306 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10307 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
10308 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10309 WIPHY_VENDOR_CMD_NEED_NETDEV |
10310 WIPHY_VENDOR_CMD_NEED_RUNNING,
10311 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
10312 },
10313#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010314#ifdef FEATURE_WLAN_TDLS
10315 {
10316 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10317 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
10318 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10319 WIPHY_VENDOR_CMD_NEED_NETDEV |
10320 WIPHY_VENDOR_CMD_NEED_RUNNING,
10321 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
10322 },
10323#endif
10324#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
10325 {
10326 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10327 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
10328 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10329 WIPHY_VENDOR_CMD_NEED_NETDEV |
10330 WIPHY_VENDOR_CMD_NEED_RUNNING,
10331 .doit = wlan_hdd_cfg80211_offloaded_packets
10332 },
10333#endif
10334 {
10335 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10336 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
10337 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10338 WIPHY_VENDOR_CMD_NEED_NETDEV |
10339 WIPHY_VENDOR_CMD_NEED_RUNNING,
10340 .doit = wlan_hdd_cfg80211_monitor_rssi
10341 },
10342 {
10343 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010344 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
10345 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10346 WIPHY_VENDOR_CMD_NEED_NETDEV |
10347 WIPHY_VENDOR_CMD_NEED_RUNNING,
10348 .doit = wlan_hdd_cfg80211_set_ns_offload
10349 },
10350 {
10351 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010352 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
10353 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10354 WIPHY_VENDOR_CMD_NEED_NETDEV |
10355 WIPHY_VENDOR_CMD_NEED_RUNNING,
10356 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
10357 },
10358#ifdef WLAN_FEATURE_MEMDUMP
10359 {
10360 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10361 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
10362 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10363 WIPHY_VENDOR_CMD_NEED_NETDEV |
10364 WIPHY_VENDOR_CMD_NEED_RUNNING,
10365 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
10366 },
10367#endif /* WLAN_FEATURE_MEMDUMP */
10368 {
10369 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10370 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
10371 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10372 WIPHY_VENDOR_CMD_NEED_NETDEV |
10373 WIPHY_VENDOR_CMD_NEED_RUNNING,
10374 .doit = wlan_hdd_cfg80211_vendor_scan
10375 },
10376
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053010377 /* Vendor abort scan */
10378 {
10379 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10380 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
10381 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10382 WIPHY_VENDOR_CMD_NEED_NETDEV |
10383 WIPHY_VENDOR_CMD_NEED_RUNNING,
10384 .doit = wlan_hdd_vendor_abort_scan
10385 },
10386
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010387 /* OCB commands */
10388 {
10389 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10390 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
10391 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10392 WIPHY_VENDOR_CMD_NEED_NETDEV |
10393 WIPHY_VENDOR_CMD_NEED_RUNNING,
10394 .doit = wlan_hdd_cfg80211_ocb_set_config
10395 },
10396 {
10397 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10398 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
10399 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10400 WIPHY_VENDOR_CMD_NEED_NETDEV |
10401 WIPHY_VENDOR_CMD_NEED_RUNNING,
10402 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
10403 },
10404 {
10405 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10406 .info.subcmd =
10407 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
10408 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10409 WIPHY_VENDOR_CMD_NEED_NETDEV |
10410 WIPHY_VENDOR_CMD_NEED_RUNNING,
10411 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
10412 },
10413 {
10414 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10415 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
10416 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10417 WIPHY_VENDOR_CMD_NEED_NETDEV |
10418 WIPHY_VENDOR_CMD_NEED_RUNNING,
10419 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
10420 },
10421 {
10422 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10423 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
10424 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10425 WIPHY_VENDOR_CMD_NEED_NETDEV |
10426 WIPHY_VENDOR_CMD_NEED_RUNNING,
10427 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
10428 },
10429 {
10430 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10431 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
10432 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10433 WIPHY_VENDOR_CMD_NEED_NETDEV |
10434 WIPHY_VENDOR_CMD_NEED_RUNNING,
10435 .doit = wlan_hdd_cfg80211_dcc_get_stats
10436 },
10437 {
10438 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10439 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
10440 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10441 WIPHY_VENDOR_CMD_NEED_NETDEV |
10442 WIPHY_VENDOR_CMD_NEED_RUNNING,
10443 .doit = wlan_hdd_cfg80211_dcc_clear_stats
10444 },
10445 {
10446 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10447 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
10448 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10449 WIPHY_VENDOR_CMD_NEED_NETDEV |
10450 WIPHY_VENDOR_CMD_NEED_RUNNING,
10451 .doit = wlan_hdd_cfg80211_dcc_update_ndl
10452 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010453 {
10454 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10455 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
10456 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10457 WIPHY_VENDOR_CMD_NEED_NETDEV |
10458 WIPHY_VENDOR_CMD_NEED_RUNNING,
10459 .doit = wlan_hdd_cfg80211_get_link_properties
10460 },
Peng Xu278d0122015-09-24 16:34:17 -070010461 {
Peng Xud2220962016-07-11 17:59:17 -070010462 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070010463 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
10464 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10465 WIPHY_VENDOR_CMD_NEED_NETDEV |
10466 WIPHY_VENDOR_CMD_NEED_RUNNING,
10467 .doit = wlan_hdd_cfg80211_set_ota_test
10468 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080010469#ifdef FEATURE_LFR_SUBNET_DETECTION
10470 {
10471 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10472 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
10473 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10474 WIPHY_VENDOR_CMD_NEED_NETDEV |
10475 WIPHY_VENDOR_CMD_NEED_RUNNING,
10476 .doit = wlan_hdd_cfg80211_set_gateway_params
10477 },
10478#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070010479 {
Peng Xud2220962016-07-11 17:59:17 -070010480 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070010481 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
10482 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10483 WIPHY_VENDOR_CMD_NEED_NETDEV |
10484 WIPHY_VENDOR_CMD_NEED_RUNNING,
10485 .doit = wlan_hdd_cfg80211_txpower_scale
10486 },
10487 {
10488 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10489 .info.subcmd =
10490 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
10491 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10492 WIPHY_VENDOR_CMD_NEED_NETDEV |
10493 WIPHY_VENDOR_CMD_NEED_RUNNING,
10494 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
10495 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010496 {
10497 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10498 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
10499 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10500 WIPHY_VENDOR_CMD_NEED_NETDEV |
10501 WIPHY_VENDOR_CMD_NEED_RUNNING,
10502 .doit = wlan_hdd_cfg80211_bpf_offload
10503 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010504 {
10505 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053010506 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
10507 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10508 WIPHY_VENDOR_CMD_NEED_NETDEV |
10509 WIPHY_VENDOR_CMD_NEED_RUNNING,
10510 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10511 },
10512 {
10513 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010514 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10515 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10516 WIPHY_VENDOR_CMD_NEED_NETDEV |
10517 WIPHY_VENDOR_CMD_NEED_RUNNING,
10518 .doit = wlan_hdd_cfg80211_sta_roam_policy
10519 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010520#ifdef FEATURE_WLAN_CH_AVOID
10521 {
10522 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10523 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10524 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10525 WIPHY_VENDOR_CMD_NEED_NETDEV |
10526 WIPHY_VENDOR_CMD_NEED_RUNNING,
10527 .doit = wlan_hdd_cfg80211_avoid_freq
10528 },
10529#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010530 {
10531 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010532 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10533 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10534 WIPHY_VENDOR_CMD_NEED_NETDEV |
10535 WIPHY_VENDOR_CMD_NEED_RUNNING,
10536 .doit = wlan_hdd_cfg80211_sap_configuration_set
10537 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010538 {
Peng Xu4225c152016-07-14 21:18:14 -070010539 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010540 .info.subcmd =
10541 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10542 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10543 WIPHY_VENDOR_CMD_NEED_NETDEV |
10544 WIPHY_VENDOR_CMD_NEED_RUNNING,
10545 .doit = wlan_hdd_cfg80211_p2p_lo_start
10546 },
10547 {
10548 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10549 .info.subcmd =
10550 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10551 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10552 WIPHY_VENDOR_CMD_NEED_NETDEV |
10553 WIPHY_VENDOR_CMD_NEED_RUNNING,
10554 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10555 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010556 {
10557 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10558 .info.subcmd =
10559 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10560 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10561 WIPHY_VENDOR_CMD_NEED_NETDEV |
10562 WIPHY_VENDOR_CMD_NEED_RUNNING,
10563 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10564 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010565#ifdef WLAN_FEATURE_NAN_DATAPATH
10566 {
10567 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10568 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10569 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10570 WIPHY_VENDOR_CMD_NEED_NETDEV |
10571 WIPHY_VENDOR_CMD_NEED_RUNNING,
10572 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10573 },
10574#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010575 {
10576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10577 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10578 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10579 WIPHY_VENDOR_CMD_NEED_NETDEV |
10580 WIPHY_VENDOR_CMD_NEED_RUNNING,
10581 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10582 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010583 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010584 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10585 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10586 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10587 WIPHY_VENDOR_CMD_NEED_NETDEV |
10588 WIPHY_VENDOR_CMD_NEED_RUNNING,
10589 .doit = wlan_hdd_cfg80211_get_bus_size
10590 },
10591 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010592 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10593 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10594 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10595 WIPHY_VENDOR_CMD_NEED_NETDEV |
10596 WIPHY_VENDOR_CMD_NEED_RUNNING,
10597 .doit = wlan_hdd_cfg80211_update_vendor_channel
10598 },
10599 {
bingsd09dea32017-03-17 10:08:26 +080010600 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010601 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10602 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10603 WIPHY_VENDOR_CMD_NEED_NETDEV |
10604 WIPHY_VENDOR_CMD_NEED_RUNNING,
10605 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010606 },
10607 {
10608 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10609 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10610 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10611 WIPHY_VENDOR_CMD_NEED_NETDEV |
10612 WIPHY_VENDOR_CMD_NEED_RUNNING,
10613 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010614 },
10615#ifdef WLAN_FEATURE_DISA
10616 {
10617 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10618 .info.subcmd =
10619 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10620 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10621 WIPHY_VENDOR_CMD_NEED_NETDEV |
10622 WIPHY_VENDOR_CMD_NEED_RUNNING,
10623 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10624 },
10625#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010626#ifdef FEATURE_WLAN_TDLS
10627 {
10628 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10629 .info.subcmd =
10630 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10631 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10632 WIPHY_VENDOR_CMD_NEED_NETDEV |
10633 WIPHY_VENDOR_CMD_NEED_RUNNING,
10634 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010635 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010636#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010637 {
10638 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10639 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10640 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10641 WIPHY_VENDOR_CMD_NEED_RUNNING,
10642 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10643 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010644 {
10645 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10646 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10647 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10648 WIPHY_VENDOR_CMD_NEED_NETDEV |
10649 WIPHY_VENDOR_CMD_NEED_RUNNING,
10650 .doit = wlan_hdd_cfg80211_set_trace_level
10651 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080010652 {
10653 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10654 .info.subcmd =
10655 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
10656 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10657 WIPHY_VENDOR_CMD_NEED_NETDEV |
10658 WIPHY_VENDOR_CMD_NEED_RUNNING,
10659 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
10660 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010661
Paul Zhang3a210c52016-12-08 10:18:12 +080010662#ifdef WLAN_UMAC_CONVERGENCE
10663 COMMON_VENDOR_COMMANDS
10664#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010665 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010666};
10667
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010668#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10669 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10670 defined(FEATURE_WLAN_SCAN_PNO)
10671/**
10672 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10673 * @wiphy: pointer to wiphy
10674 * @config: pointer to config
10675 *
10676 * Return: None
10677 */
10678static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10679 struct hdd_config *config)
10680{
10681 if (config->configPNOScanSupport) {
10682 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010683 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10684 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010685 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010686 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010687 if (config->max_sched_scan_plan_interval)
10688 wiphy->max_sched_scan_plan_interval =
10689 config->max_sched_scan_plan_interval;
10690 if (config->max_sched_scan_plan_iterations)
10691 wiphy->max_sched_scan_plan_iterations =
10692 config->max_sched_scan_plan_iterations;
10693 }
10694}
10695#else
10696static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10697 struct hdd_config *config)
10698{
10699}
10700#endif
10701
10702
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010703/**
10704 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10705 * @priv_size: Size of the hdd context.
10706 *
10707 * Allocate wiphy context and hdd context.
10708 *
10709 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010710 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010711hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010712{
10713 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010714 hdd_context_t *hdd_ctx;
10715
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010716 ENTER();
10717
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010718 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10719
10720 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010721 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010722 return NULL;
10723 }
10724
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010725 hdd_ctx = wiphy_priv(wiphy);
10726
10727 hdd_ctx->wiphy = wiphy;
10728
10729 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010730}
10731
10732/*
10733 * FUNCTION: wlan_hdd_cfg80211_update_band
10734 * This function is called from the supplicant through a
10735 * private ioctl to change the band value
10736 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010737int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10738 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010739{
10740 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010741 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010742
10743 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010744 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010745
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010746 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010747 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010748
10749 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10750 struct ieee80211_supported_band *band = wiphy->bands[i];
10751
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010752 channelEnabledState = wlan_reg_get_channel_state(
10753 hdd_ctx->hdd_pdev,
10754 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010755
Dustin Browna30892e2016-10-12 17:28:36 -070010756 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010757 /* 5G only */
10758#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10759 /* Enable Social channels for P2P */
10760 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10761 (band->channels[j].center_freq)
10762 && CHANNEL_STATE_ENABLE ==
10763 channelEnabledState)
10764 band->channels[j].flags &=
10765 ~IEEE80211_CHAN_DISABLED;
10766 else
10767#endif
10768 band->channels[j].flags |=
10769 IEEE80211_CHAN_DISABLED;
10770 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010771 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010772 eCSR_BAND_24 == eBand) {
10773 /* 2G only */
10774 band->channels[j].flags |=
10775 IEEE80211_CHAN_DISABLED;
10776 continue;
10777 }
10778
Amar Singhal6842e8f2016-02-23 16:30:32 -080010779 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010780 band->channels[j].flags &=
10781 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010782 }
10783 }
10784 return 0;
10785}
10786
Peng Xuacfdda12017-02-06 16:15:38 -080010787#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788/*
10789 * FUNCTION: wlan_hdd_cfg80211_init
10790 * This function is called by hdd_wlan_startup()
10791 * during initialization.
10792 * This function is used to initialize and register wiphy structure.
10793 */
10794int wlan_hdd_cfg80211_init(struct device *dev,
10795 struct wiphy *wiphy, struct hdd_config *pCfg)
10796{
10797 int i, j;
10798 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10799
10800 ENTER();
10801
10802 /* Now bind the underlying wlan device with wiphy */
10803 set_wiphy_dev(wiphy, dev);
10804
10805 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10806
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010807 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10808 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10809 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10810#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10811 | WIPHY_FLAG_4ADDR_STATION
10812#endif
10813 | WIPHY_FLAG_OFFCHAN_TX;
10814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010815#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10816 wiphy->wowlan = &wowlan_support_cfg80211_init;
10817#else
10818 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10819 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10820 wiphy->wowlan.pattern_min_len = 1;
10821 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10822#endif
10823
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010824 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010825#ifdef FEATURE_WLAN_ESE
10826 || pCfg->isEseIniFeatureEnabled
10827#endif
10828 ) {
10829 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10830 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831#ifdef FEATURE_WLAN_TDLS
10832 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10833 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10834#endif
10835
10836 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10837
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010838#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10839 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10840#endif
10841
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010842 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010843
10844#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010845 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010846#endif
10847
10848 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010849 * driver can still register regulatory callback and
10850 * it will get regulatory settings in wiphy->band[], but
10851 * driver need to determine what to do with both
10852 * regulatory settings
10853 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010854
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010855#if defined QCA_WIFI_FTM
10856}
10857#endif
10858
10859 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10860
10861 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10862
10863 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10864
Arun Khandavallifae92942016-08-01 13:31:08 +053010865 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10866 | BIT(NL80211_IFTYPE_ADHOC)
10867 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10868 | BIT(NL80211_IFTYPE_P2P_GO)
10869 | BIT(NL80211_IFTYPE_AP)
10870 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010871
Arun Khandavallifae92942016-08-01 13:31:08 +053010872 if (pCfg->advertiseConcurrentOperation) {
10873 if (pCfg->enableMCC) {
10874 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010875
Arun Khandavallifae92942016-08-01 13:31:08 +053010876 for (i = 0;
10877 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10878 i++) {
10879 if (!pCfg->allowMCCGODiffBI)
10880 wlan_hdd_iface_combination[i].
10881 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010882 }
10883 }
10884 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010885 ARRAY_SIZE(wlan_hdd_iface_combination);
10886 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887 }
10888
10889 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010890 * on ini values
10891 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010892 if (!pCfg->ShortGI20MhzEnable) {
10893 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10894 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895 }
10896
10897 if (!pCfg->ShortGI40MhzEnable) {
10898 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10899 }
10900
10901 if (!pCfg->nChannelBondingMode5GHz) {
10902 wlan_hdd_band_5_ghz.ht_cap.cap &=
10903 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10904 }
10905
Abhishek Singhf512bf32016-05-04 16:47:46 +053010906 /*
10907 * In case of static linked driver at the time of driver unload,
10908 * module exit doesn't happens. Module cleanup helps in cleaning
10909 * of static memory.
10910 * If driver load happens statically, at the time of driver unload,
10911 * wiphy flags don't get reset because of static memory.
10912 * It's better not to store channel in static memory.
10913 */
Dustin Browna30892e2016-10-12 17:28:36 -070010914 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10915 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010916 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010917 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010918 hdd_err("Not enough memory to allocate channels");
10919 return -ENOMEM;
10920 }
Dustin Browna30892e2016-10-12 17:28:36 -070010921 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010922 &hdd_channels_2_4_ghz[0],
10923 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010924 if ((hdd_is_5g_supported(pHddCtx)) &&
10925 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10926 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10927 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10928 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010929 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10930 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010931 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010932 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010933 hdd_err("Not enough memory to allocate channels");
10934 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010935 bands[NL80211_BAND_2GHZ]->channels);
10936 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010937 return -ENOMEM;
10938 }
Dustin Browna30892e2016-10-12 17:28:36 -070010939 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010940 &hdd_channels_5_ghz[0],
10941 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010942 }
10943
Dustin Browna30892e2016-10-12 17:28:36 -070010944 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010945
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010946 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010947 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948
10949 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10950 struct ieee80211_supported_band *band = wiphy->bands[i];
10951
Dustin Browna30892e2016-10-12 17:28:36 -070010952 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010953 eCSR_BAND_5G == pCfg->nBandCapability) {
10954 /* 5G only */
10955#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10956 /* Enable social channels for P2P */
10957 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10958 (band->channels[j].center_freq))
10959 band->channels[j].flags &=
10960 ~IEEE80211_CHAN_DISABLED;
10961 else
10962#endif
10963 band->channels[j].flags |=
10964 IEEE80211_CHAN_DISABLED;
10965 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010966 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010967 eCSR_BAND_24 == pCfg->nBandCapability) {
10968 /* 2G only */
10969 band->channels[j].flags |=
10970 IEEE80211_CHAN_DISABLED;
10971 continue;
10972 }
10973 }
10974 }
10975 /*Initialise the supported cipher suite details */
10976 wiphy->cipher_suites = hdd_cipher_suites;
10977 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10978
10979 /*signal strength in mBm (100*dBm) */
10980 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10981 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10982
Anurag Chouhan6d760662016-02-20 16:05:43 +053010983 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010984 wiphy->n_vendor_commands =
10985 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10986 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10987
10988 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10989 wiphy->n_vendor_events =
10990 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10991 }
10992
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993 if (pCfg->enableDFSMasterCap) {
10994 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10995 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010996
10997 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10998
10999#ifdef QCA_HT_2040_COEX
11000 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
11001#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053011002 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080011003
11004#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
11005 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
11006 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
11007 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
11008 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
11009#endif
11010
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011011 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080011012 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011013
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011014 EXIT();
11015 return 0;
11016}
11017
Abhishek Singhf512bf32016-05-04 16:47:46 +053011018/**
Yingying Tang80e15f32016-09-27 18:23:01 +080011019 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
11020 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053011021 *
11022 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053011023 * memory allocated in wlan_hdd_cfg80211_init also
11024 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053011025 *
11026 * Return: void
11027 */
11028void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
11029{
11030 int i;
11031
Dustin Browna30892e2016-10-12 17:28:36 -070011032 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053011033 if (NULL != wiphy->bands[i] &&
11034 (NULL != wiphy->bands[i]->channels)) {
11035 qdf_mem_free(wiphy->bands[i]->channels);
11036 wiphy->bands[i]->channels = NULL;
11037 }
11038 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080011039
Abhishek Singh3e6172f2016-05-04 16:56:48 +053011040 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053011041}
11042
Yingying Tang80e15f32016-09-27 18:23:01 +080011043/**
11044 * wlan_hdd_update_band_cap() - update capabilities for supported bands
11045 * @hdd_ctx: HDD context
11046 *
11047 * this function will update capabilities for supported bands
11048 *
11049 * Return: void
11050 */
11051static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
11052{
11053 uint32_t val32;
11054 uint16_t val16;
11055 tSirMacHTCapabilityInfo *ht_cap_info;
11056 QDF_STATUS status;
11057
11058 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
11059 if (QDF_STATUS_SUCCESS != status) {
11060 hdd_err("could not get HT capability info");
11061 val32 = 0;
11062 }
11063 val16 = (uint16_t)val32;
11064 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
11065
11066 if (ht_cap_info->txSTBC == true) {
11067 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
11068 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
11069 IEEE80211_HT_CAP_TX_STBC;
11070 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
11071 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
11072 IEEE80211_HT_CAP_TX_STBC;
11073 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011074
11075 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
11076 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
11077 vht_cap.vht_supported = 0;
11078 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
11079 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
11080 vht_cap.vht_supported = 0;
11081 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
11082 }
Yingying Tang80e15f32016-09-27 18:23:01 +080011083}
11084
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011085/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011086 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011087 * initialization. In wlan_hdd_cfg80211_init, only the
11088 * default values will be initialized. The final initialization
11089 * of all required members can be done here.
11090 */
Yingying Tang80e15f32016-09-27 18:23:01 +080011091void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011092{
Yingying Tang80e15f32016-09-27 18:23:01 +080011093 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
11094
11095 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096}
11097
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011098/**
11099 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
11100 * @cfg: hdd cfg
11101 *
11102 * this function update 11n mode in hdd cfg
11103 *
11104 * Return: void
11105 */
11106void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
11107{
11108 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011109 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011110 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011111 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011112 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
11113 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
11114 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
11115 cfg->sap_p2p_11ac_override = 0;
11116 }
11117 }
11118}
11119
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011120/* In this function we are registering wiphy. */
11121int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
11122{
11123 ENTER();
11124 /* Register our wiphy dev with cfg80211 */
11125 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011126 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011127 return -EIO;
11128 }
11129
11130 EXIT();
11131 return 0;
11132}
11133
11134/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011135 * HDD function to update wiphy capability based on target offload status.
11136 *
11137 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
11138 * capability even before downloading firmware to the target. In discrete
11139 * case, host will get know certain offload capability (say sched_scan
11140 * caps) only after downloading firmware to the target and target boots up.
11141 * This function is used to override setting done in wlan_hdd_cfg80211_init()
11142 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011143 */
11144void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
11145{
11146#ifdef FEATURE_WLAN_SCAN_PNO
11147 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
11148 struct hdd_config *pCfg = pHddCtx->config;
11149
11150 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
11151 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011152 * have PNO support.
11153 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011154 if (!pCfg->PnoOffload) {
11155 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
11156 wiphy->max_sched_scan_ssids = 0;
11157 wiphy->max_match_sets = 0;
11158 wiphy->max_sched_scan_ie_len = 0;
11159 }
11160#endif
11161}
11162
11163/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011164#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
11165
Wu Gao84d120c2017-03-24 18:46:00 +080011166void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
11167{
11168 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11169 /* Register for all P2P action, public action etc frames */
11170 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11171
11172 ENTER();
11173
11174 /* Register frame indication call back */
11175 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
11176
11177 /* Register for p2p ack indication */
11178 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
11179
11180 /* Right now we are registering these frame when driver is getting
11181 * initialized. Once we will move to 2.6.37 kernel, in which we have
11182 * frame register ops, we will move this code as a part of that
11183 */
11184
11185 /* GAS Initial Request */
11186 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11187 (uint8_t *) GAS_INITIAL_REQ,
11188 GAS_INITIAL_REQ_SIZE);
11189
11190 /* GAS Initial Response */
11191 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11192 (uint8_t *) GAS_INITIAL_RSP,
11193 GAS_INITIAL_RSP_SIZE);
11194
11195 /* GAS Comeback Request */
11196 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11197 (uint8_t *) GAS_COMEBACK_REQ,
11198 GAS_COMEBACK_REQ_SIZE);
11199
11200 /* GAS Comeback Response */
11201 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11202 (uint8_t *) GAS_COMEBACK_RSP,
11203 GAS_COMEBACK_RSP_SIZE);
11204
11205 /* WNM BSS Transition Request frame */
11206 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11207 (uint8_t *) WNM_BSS_ACTION_FRAME,
11208 WNM_BSS_ACTION_FRAME_SIZE);
11209
11210 /* WNM-Notification */
11211 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
11212 (uint8_t *) WNM_NOTIFICATION_FRAME,
11213 WNM_NOTIFICATION_FRAME_SIZE);
11214}
11215#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011216void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
11217{
11218 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11219 /* Register for all P2P action, public action etc frames */
11220 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11221
11222 ENTER();
11223
Abhishek Singh7996eb72015-12-30 17:24:02 +053011224 /* Register frame indication call back */
11225 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
11226
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053011227 /* Register for p2p ack indication */
11228 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
11229
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011230 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011231 * initialized. Once we will move to 2.6.37 kernel, in which we have
11232 * frame register ops, we will move this code as a part of that
11233 */
11234
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011235 /* GAS Initial Request */
11236 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11237 (uint8_t *) GAS_INITIAL_REQ,
11238 GAS_INITIAL_REQ_SIZE);
11239
11240 /* GAS Initial Response */
11241 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11242 (uint8_t *) GAS_INITIAL_RSP,
11243 GAS_INITIAL_RSP_SIZE);
11244
11245 /* GAS Comeback Request */
11246 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11247 (uint8_t *) GAS_COMEBACK_REQ,
11248 GAS_COMEBACK_REQ_SIZE);
11249
11250 /* GAS Comeback Response */
11251 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11252 (uint8_t *) GAS_COMEBACK_RSP,
11253 GAS_COMEBACK_RSP_SIZE);
11254
11255 /* P2P Public Action */
11256 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11257 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11258 P2P_PUBLIC_ACTION_FRAME_SIZE);
11259
11260 /* P2P Action */
11261 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11262 (uint8_t *) P2P_ACTION_FRAME,
11263 P2P_ACTION_FRAME_SIZE);
11264
11265 /* WNM BSS Transition Request frame */
11266 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11267 (uint8_t *) WNM_BSS_ACTION_FRAME,
11268 WNM_BSS_ACTION_FRAME_SIZE);
11269
11270 /* WNM-Notification */
11271 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
11272 (uint8_t *) WNM_NOTIFICATION_FRAME,
11273 WNM_NOTIFICATION_FRAME_SIZE);
11274}
Wu Gao84d120c2017-03-24 18:46:00 +080011275#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011276
11277void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
11278{
11279 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11280 /* Register for all P2P action, public action etc frames */
11281 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11282
11283 ENTER();
11284
11285 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011286 * initialized. Once we will move to 2.6.37 kernel, in which we have
11287 * frame register ops, we will move this code as a part of that
11288 */
11289
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011290 /* GAS Initial Request */
11291
11292 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11293 (uint8_t *) GAS_INITIAL_REQ,
11294 GAS_INITIAL_REQ_SIZE);
11295
11296 /* GAS Initial Response */
11297 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11298 (uint8_t *) GAS_INITIAL_RSP,
11299 GAS_INITIAL_RSP_SIZE);
11300
11301 /* GAS Comeback Request */
11302 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11303 (uint8_t *) GAS_COMEBACK_REQ,
11304 GAS_COMEBACK_REQ_SIZE);
11305
11306 /* GAS Comeback Response */
11307 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11308 (uint8_t *) GAS_COMEBACK_RSP,
11309 GAS_COMEBACK_RSP_SIZE);
11310
11311 /* P2P Public Action */
11312 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11313 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11314 P2P_PUBLIC_ACTION_FRAME_SIZE);
11315
11316 /* P2P Action */
11317 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11318 (uint8_t *) P2P_ACTION_FRAME,
11319 P2P_ACTION_FRAME_SIZE);
11320
11321 /* WNM-Notification */
11322 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
11323 (uint8_t *) WNM_NOTIFICATION_FRAME,
11324 WNM_NOTIFICATION_FRAME_SIZE);
11325}
11326
11327#ifdef FEATURE_WLAN_WAPI
11328void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
11329 const uint8_t *mac_addr, const uint8_t *key,
11330 int key_Len)
11331{
11332 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11333 tCsrRoamSetKey setKey;
11334 bool isConnected = true;
11335 int status = 0;
11336 uint32_t roamId = 0xFF;
11337 uint8_t *pKeyPtr = NULL;
11338 int n = 0;
11339
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011340 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011341 hdd_device_mode_to_string(pAdapter->device_mode),
11342 pAdapter->device_mode);
11343
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011344 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011345 setKey.keyId = key_index; /* Store Key ID */
11346 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
11347 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
11348 setKey.paeRole = 0; /* the PAE role */
11349 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053011350 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011351 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011352 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 }
11354 setKey.keyLength = key_Len;
11355 pKeyPtr = setKey.Key;
11356 memcpy(pKeyPtr, key, key_Len);
11357
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011358 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011359 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011360 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070011361 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011362
11363 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11364 if (isConnected) {
11365 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11366 pAdapter->sessionId, &setKey, &roamId);
11367 }
11368 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011369 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
11371 }
11372}
11373#endif /* FEATURE_WLAN_WAPI */
11374
11375uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
11376 uint8_t eid)
11377{
11378 int left = length;
11379 uint8_t *ptr = (uint8_t *)ies_ptr;
11380 uint8_t elem_id, elem_len;
11381
11382 while (left >= 2) {
11383 elem_id = ptr[0];
11384 elem_len = ptr[1];
11385 left -= 2;
11386 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011387 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011388 eid, elem_len, left);
11389 return NULL;
11390 }
11391 if (elem_id == eid) {
11392 return ptr;
11393 }
11394
11395 left -= elem_len;
11396 ptr += (elem_len + 2);
11397 }
11398 return NULL;
11399}
11400
Krunal Soni364e0872017-05-10 21:24:34 -070011401bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
11402{
11403 uint8_t *vendor_ie;
11404
11405 if (length < 2) {
11406 hdd_debug("bss size is less than expected");
11407 return true;
11408 }
11409 if (!ies) {
11410 hdd_debug("invalid IE pointer");
11411 return true;
11412 }
11413 vendor_ie = wlan_hdd_get_vendor_oui_ie_ptr(VENDOR1_AP_OUI_TYPE,
11414 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
11415 if (vendor_ie) {
11416 hdd_debug("AP can't support immediate powersave. defer it");
11417 return false;
11418 }
11419 return true;
11420}
11421
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011422/*
11423 * FUNCTION: wlan_hdd_validate_operation_channel
11424 * called by wlan_hdd_cfg80211_start_bss() and
11425 * wlan_hdd_set_channel()
11426 * This function validates whether given channel is part of valid
11427 * channel list.
11428 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011429QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011430 int channel)
11431{
11432
11433 uint32_t num_ch = 0;
11434 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11435 u32 indx = 0;
11436 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11437 uint8_t fValidChannel = false, count = 0;
11438 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
11439
11440 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11441
11442 if (hdd_pConfig_ini->sapAllowAllChannel) {
11443 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080011444 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011445 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011446 fValidChannel = true;
11447 break;
11448 }
11449 }
11450 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011451 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011452 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011453 }
11454 } else {
11455 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
11456 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011457 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011458 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011459 }
11460 for (indx = 0; indx < num_ch; indx++) {
11461 if (channel == valid_ch[indx]) {
11462 break;
11463 }
11464 }
11465
11466 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011467 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011468 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011469 }
11470 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011471 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011472
11473}
11474
11475#ifdef DHCP_SERVER_OFFLOAD
11476static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
11477{
11478 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
11479 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
11480 uint8_t numEntries = 0;
11481 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
11482 uint8_t num;
11483 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011484 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011485 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070011486 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011487 return;
11488 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011489 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
11490 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
11491 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
11492 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
11493 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
11494 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011495 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011496 goto end;
11497 }
11498 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011499 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011500 goto end;
11501 }
11502 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011503 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011504 goto end;
11505 }
11506 for (num = 0; num < numEntries; num++) {
11507 temp = srv_ip[num];
11508 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
11509 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011510 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011512 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513 goto end;
11514 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011515 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011516end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011517 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011518 return;
11519}
11520#endif /* DHCP_SERVER_OFFLOAD */
11521
11522static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11523 struct net_device *dev,
11524 struct bss_parameters *params)
11525{
11526 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11527 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11528 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011529 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011530
11531 ENTER();
11532
Anurag Chouhan6d760662016-02-20 16:05:43 +053011533 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011534 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011535 return -EINVAL;
11536 }
11537
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011538 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11539 hdd_err("invalid session id: %d", pAdapter->sessionId);
11540 return -EINVAL;
11541 }
11542
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011543 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011544 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11545 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011546 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011547 hdd_device_mode_to_string(pAdapter->device_mode),
11548 pAdapter->device_mode, params->ap_isolate);
11549
11550 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11551 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011552 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011553 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011554
Krunal Sonib4326f22016-03-10 13:05:51 -080011555 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11556 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557 return -EOPNOTSUPP;
11558 }
11559
11560 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011561 * want to update this parameter
11562 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011563 if (-1 != params->ap_isolate) {
11564 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11565 !!params->ap_isolate;
11566
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011567 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011568 pAdapter->sessionId,
11569 pAdapter->sessionCtx.
11570 ap.
11571 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011572 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011573 ret = -EINVAL;
11574 }
11575 }
11576
11577 EXIT();
11578 return ret;
11579}
11580
Krunal Soni8c37e322016-02-03 16:08:37 -080011581/**
11582 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11583 * @ndev: pointer to net device provided by supplicant
11584 * @type: type of the interface, upper layer wanted to change
11585 *
11586 * Upper layer provides the new interface mode that needs to be changed
11587 * for given net device
11588 *
11589 * Return: success or failure in terms of integer value
11590 */
11591static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011592 enum nl80211_iftype type)
11593{
Krunal Soni8c37e322016-02-03 16:08:37 -080011594 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11595 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11596 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011597 hdd_wext_state_t *wext;
11598 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011599 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011600
11601 ENTER();
11602
Krunal Soni8c37e322016-02-03 16:08:37 -080011603 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011604 hdd_warn("ACS is in progress, don't change iface!");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011605 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011606 }
11607
11608 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011609 hdd_stop_adapter(hdd_ctx, adapter, true);
11610 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011611 wdev->iftype = type;
11612 /*Check for sub-string p2p to confirm its a p2p interface */
11613 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011614 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011615 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011616 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011617 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011618 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011619 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011620 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011621 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011622 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011623 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011624 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11625 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011626 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11627 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011628 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011629 adapter->scan_info.scanAddIE.length;
11630 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011631 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011632 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11633 wext->roamProfile.phyMode =
11634 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11635 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011636 EXIT();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011637
11638 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011639}
11640
11641static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11642 struct net_device *dev,
11643 struct bss_parameters *params)
11644{
11645 int ret;
11646
11647 cds_ssr_protect(__func__);
11648 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11649 cds_ssr_unprotect(__func__);
11650
11651 return ret;
11652}
11653
11654/* FUNCTION: wlan_hdd_change_country_code_cd
11655 * to wait for contry code completion
11656 */
11657void *wlan_hdd_change_country_code_cb(void *pAdapter)
11658{
11659 hdd_adapter_t *call_back_pAdapter = pAdapter;
11660 complete(&call_back_pAdapter->change_country_code);
11661 return NULL;
11662}
11663
Rajeev Kumar98edb772016-01-19 12:42:19 -080011664/**
11665 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11666 * @wiphy: Pointer to the wiphy structure
11667 * @ndev: Pointer to the net device
11668 * @type: Interface type
11669 * @flags: Flags for change interface
11670 * @params: Pointer to change interface parameters
11671 *
11672 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011673 */
11674static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11675 struct net_device *ndev,
11676 enum nl80211_iftype type,
11677 u32 *flags,
11678 struct vif_params *params)
11679{
11680 struct wireless_dev *wdev;
11681 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11682 hdd_context_t *pHddCtx;
11683 tCsrRoamProfile *pRoamProfile = NULL;
11684 eCsrRoamBssType LastBSSType;
11685 struct hdd_config *pConfig = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011686 int status;
11687
11688 ENTER();
11689
Anurag Chouhan6d760662016-02-20 16:05:43 +053011690 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011691 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011692 return -EINVAL;
11693 }
11694
11695 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11696 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011697 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011698 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011699
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011700 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011701 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11702 pAdapter->sessionId, type));
11703
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011704 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011705 pAdapter->device_mode, type);
11706
Arun Khandavallifae92942016-08-01 13:31:08 +053011707 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11708 if (status) {
11709 hdd_err("Failed to start modules");
11710 return -EINVAL;
11711 }
11712
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011713 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11715 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011716 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011717 return -EINVAL;
11718 }
11719
11720 pConfig = pHddCtx->config;
11721 wdev = ndev->ieee80211_ptr;
11722
11723 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011724 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11725 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011726
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011727 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011728 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011729 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11730 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11731 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11732 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011733 hdd_wext_state_t *pWextState =
11734 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11735
11736 pRoamProfile = &pWextState->roamProfile;
11737 LastBSSType = pRoamProfile->BSSType;
11738
11739 switch (type) {
11740 case NL80211_IFTYPE_STATION:
11741 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011742 case NL80211_IFTYPE_ADHOC:
11743 if (type == NL80211_IFTYPE_ADHOC) {
11744 wlan_hdd_tdls_exit(pAdapter);
11745 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011746 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011747 }
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011748 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
Krunal Soni8c37e322016-02-03 16:08:37 -080011749 type);
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011750 if (status) {
11751 hdd_err("Failed to change iface to new mode:%d status %d",
11752 type, status);
11753 return status;
11754 }
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011755 if (hdd_start_adapter(pAdapter)) {
11756 hdd_err("Failed to start adapter :%d",
11757 pAdapter->device_mode);
11758 return -EINVAL;
11759 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011760 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011761 case NL80211_IFTYPE_AP:
11762 case NL80211_IFTYPE_P2P_GO:
11763 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011764 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011765 (type ==
11766 NL80211_IFTYPE_AP) ? "SoftAP" :
11767 "P2pGo");
11768
11769 /* Cancel any remain on channel for GO mode */
11770 if (NL80211_IFTYPE_P2P_GO == type) {
11771 wlan_hdd_cancel_existing_remain_on_channel
11772 (pAdapter);
11773 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011774
Arun Khandavallifae92942016-08-01 13:31:08 +053011775 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011776 /* De-init the adapter */
11777 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11778 memset(&pAdapter->sessionCtx, 0,
11779 sizeof(pAdapter->sessionCtx));
11780 pAdapter->device_mode =
11781 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011782 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11783 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784
11785 /*
11786 * Fw will take care incase of concurrency
11787 */
11788
Krunal Sonib4326f22016-03-10 13:05:51 -080011789 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011790 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011791 /* To meet Android requirements create
11792 * a randomized MAC address of the
11793 * form 02:1A:11:Fx:xx:xx
11794 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011795 get_random_bytes(&ndev->dev_addr[3], 3);
11796 ndev->dev_addr[0] = 0x02;
11797 ndev->dev_addr[1] = 0x1A;
11798 ndev->dev_addr[2] = 0x11;
11799 ndev->dev_addr[3] |= 0xF0;
11800 memcpy(pAdapter->macAddressCurrent.
11801 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011802 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011803 pr_info("wlan: Generated HotSpot BSSID "
11804 MAC_ADDRESS_STR "\n",
11805 MAC_ADDR_ARRAY(ndev->dev_addr));
11806 }
11807
11808 hdd_set_ap_ops(pAdapter->dev);
11809
Arun Khandavallifae92942016-08-01 13:31:08 +053011810 if (hdd_start_adapter(pAdapter)) {
11811 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011812 return -EINVAL;
11813 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011814 /* Interface type changed update in wiphy structure */
11815 if (wdev) {
11816 wdev->iftype = type;
11817 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011818 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011819 return -EINVAL;
11820 }
11821 goto done;
11822 }
11823
11824 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011825 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 return -EOPNOTSUPP;
11827 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011828 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11829 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011830 switch (type) {
11831 case NL80211_IFTYPE_STATION:
11832 case NL80211_IFTYPE_P2P_CLIENT:
11833 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011834 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11835 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011836 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011838 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011839 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011840 pAdapter->device_mode);
11841 return -EINVAL;
11842 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011843 goto done;
11844
11845 case NL80211_IFTYPE_AP:
11846 case NL80211_IFTYPE_P2P_GO:
11847 wdev->iftype = type;
11848 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011849 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011850 goto done;
11851
11852 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011853 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011854 return -EOPNOTSUPP;
11855 }
11856 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011857 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011858 pAdapter->device_mode);
11859 return -EOPNOTSUPP;
11860 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011861done:
11862 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011863 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11864 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011865
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011866 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011867
11868 EXIT();
11869 return 0;
11870}
11871
Rajeev Kumar98edb772016-01-19 12:42:19 -080011872/**
11873 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11874 * @wiphy: Pointer to the wiphy structure
11875 * @ndev: Pointer to the net device
11876 * @type: Interface type
11877 * @flags: Flags for change interface
11878 * @params: Pointer to change interface parameters
11879 *
11880 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011881 */
11882static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11883 struct net_device *ndev,
11884 enum nl80211_iftype type,
11885 u32 *flags,
11886 struct vif_params *params)
11887{
11888 int ret;
11889
11890 cds_ssr_protect(__func__);
11891 ret =
11892 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11893 cds_ssr_unprotect(__func__);
11894
11895 return ret;
11896}
11897
Frank Liud4b2fa02017-03-29 11:46:48 +080011898#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011899static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11900 int index, uint8_t match)
11901{
11902 int i;
11903 for (i = 0; i < index; i++) {
11904 if (arr[i] == match)
11905 return true;
11906 }
11907 return false;
11908}
11909#endif
11910
11911/**
11912 * __wlan_hdd_change_station() - change station
11913 * @wiphy: Pointer to the wiphy structure
11914 * @dev: Pointer to the net device.
11915 * @mac: bssid
11916 * @params: Pointer to station parameters
11917 *
11918 * Return: 0 for success, error number on failure.
11919 */
11920#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11921static int __wlan_hdd_change_station(struct wiphy *wiphy,
11922 struct net_device *dev,
11923 const uint8_t *mac,
11924 struct station_parameters *params)
11925#else
11926static int __wlan_hdd_change_station(struct wiphy *wiphy,
11927 struct net_device *dev,
11928 uint8_t *mac,
11929 struct station_parameters *params)
11930#endif
11931{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011932 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011933 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11934 hdd_context_t *pHddCtx;
11935 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011936 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011937#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011938 tCsrStaParams StaParams = { 0 };
11939 uint8_t isBufSta = 0;
11940 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011941 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011942#endif
11943 int ret;
11944
11945 ENTER();
11946
Anurag Chouhan6d760662016-02-20 16:05:43 +053011947 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011948 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011949 return -EINVAL;
11950 }
11951
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011952 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011953 TRACE_CODE_HDD_CHANGE_STATION,
11954 pAdapter->sessionId, params->listen_interval));
11955
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011956 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11957 hdd_err("invalid session id: %d", pAdapter->sessionId);
11958 return -EINVAL;
11959 }
11960
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011961 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11962 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011963 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011964 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011965
11966 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11967
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011968 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011969
Krunal Sonib4326f22016-03-10 13:05:51 -080011970 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11971 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011972 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11973 status =
11974 hdd_softap_change_sta_state(pAdapter,
11975 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011976 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011977
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011978 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011979 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011980 return -EINVAL;
11981 }
11982 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011983 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11984 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011985 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011986#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11987 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11988 dev, mac, params);
11989#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011990
11991 if (cds_is_sub_20_mhz_enabled()) {
11992 hdd_err("TDLS not allowed with sub 20 MHz");
11993 return -EINVAL;
11994 }
11995
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011996 StaParams.capability = params->capability;
11997 StaParams.uapsd_queues = params->uapsd_queues;
11998 StaParams.max_sp = params->max_sp;
11999
12000 /* Convert (first channel , number of channels) tuple to
12001 * the total list of channels. This goes with the assumption
12002 * that if the first channel is < 14, then the next channels
12003 * are an incremental of 1 else an incremental of 4 till the number
12004 * of channels.
12005 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012006 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012007 if (0 != params->supported_channels_len) {
12008 int i = 0, j = 0, k = 0, no_of_channels = 0;
12009 int num_unique_channels;
12010 int next;
12011 for (i = 0;
12012 i < params->supported_channels_len
12013 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
12014 int wifi_chan_index;
12015 if (!wlan_hdd_is_duplicate_channel
12016 (StaParams.supported_channels, j,
12017 params->supported_channels[i])) {
12018 StaParams.
12019 supported_channels[j] =
12020 params->
12021 supported_channels[i];
12022 } else {
12023 continue;
12024 }
12025 wifi_chan_index =
12026 ((StaParams.supported_channels[j] <=
12027 HDD_CHANNEL_14) ? 1 : 4);
12028 no_of_channels =
12029 params->supported_channels[i + 1];
12030
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012031 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 -080012032 StaParams.
12033 supported_channels[j],
12034 wifi_chan_index,
12035 no_of_channels);
12036 for (k = 1; k <= no_of_channels &&
12037 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
12038 k++) {
12039 next =
12040 StaParams.
12041 supported_channels[j] +
12042 wifi_chan_index;
12043 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
12044 StaParams.
12045 supported_channels[j
12046 +
12047 1]
12048 = next;
12049 } else {
12050 continue;
12051 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012052 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012053 j + 1,
12054 StaParams.
12055 supported_channels[j +
12056 1]);
12057 j += 1;
12058 }
12059 }
12060 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012061 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012062 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012063 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012064 StaParams.
12065 supported_channels[i]);
12066 }
12067 if (MAX_CHANNEL < num_unique_channels)
12068 num_unique_channels = MAX_CHANNEL;
12069 StaParams.supported_channels_len =
12070 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012071 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012072 StaParams.supported_channels_len);
12073 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012074 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012075 params->supported_oper_classes,
12076 params->supported_oper_classes_len);
12077 StaParams.supported_oper_classes_len =
12078 params->supported_oper_classes_len;
12079
12080 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012081 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012082 params->ext_capab,
12083 sizeof(StaParams.extn_capability));
12084
12085 if (NULL != params->ht_capa) {
12086 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012087 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012088 sizeof(tSirHTCap));
12089 }
12090
12091 StaParams.supported_rates_len =
12092 params->supported_rates_len;
12093
12094 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
12095 * The supported_rates array , for all the structures propogating till Add Sta
12096 * to the firmware has to be modified , if the supplicant (ieee80211) is
12097 * modified to send more rates.
12098 */
12099
12100 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
12101 */
12102 if (StaParams.supported_rates_len >
12103 SIR_MAC_MAX_SUPP_RATES)
12104 StaParams.supported_rates_len =
12105 SIR_MAC_MAX_SUPP_RATES;
12106
12107 if (0 != StaParams.supported_rates_len) {
12108 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012109 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012110 params->supported_rates,
12111 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012112 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012113 StaParams.supported_rates_len);
12114 for (i = 0; i < StaParams.supported_rates_len;
12115 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012116 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 StaParams.supported_rates[i]);
12118 }
12119
12120 if (NULL != params->vht_capa) {
12121 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012122 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123 params->vht_capa,
12124 sizeof(tSirVHTCap));
12125 }
12126
12127 if (0 != params->ext_capab_len) {
12128 /*Define A Macro : TODO Sunil */
12129 if ((1 << 4) & StaParams.extn_capability[3]) {
12130 isBufSta = 1;
12131 }
12132 /* TDLS Channel Switching Support */
12133 if ((1 << 6) & StaParams.extn_capability[3]) {
12134 isOffChannelSupported = 1;
12135 }
12136 }
12137
Nitesh Shah99934ac2016-09-05 15:54:08 +053012138 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053012139 (params->ht_capa || params->vht_capa ||
12140 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053012141 is_qos_wmm_sta = true;
12142
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012143 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053012144 " is_qos_wmm_sta= %d HTcapPresent = %d",
12145 __func__, is_qos_wmm_sta,
12146 StaParams.htcap_present);
12147
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012148 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053012149 &StaParams,
12150 isBufSta,
12151 isOffChannelSupported,
12152 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012153 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012154 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012155 return -EINVAL;
12156 }
12157
12158 status =
12159 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
12160 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012161 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012162 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012163 return -EINVAL;
12164 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012165#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080012166 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012167 }
12168 EXIT();
12169 return ret;
12170}
12171
12172/**
12173 * wlan_hdd_change_station() - cfg80211 change station handler function
12174 * @wiphy: Pointer to the wiphy structure
12175 * @dev: Pointer to the net device.
12176 * @mac: bssid
12177 * @params: Pointer to station parameters
12178 *
12179 * This is the cfg80211 change station handler function which invokes
12180 * the internal function @__wlan_hdd_change_station with
12181 * SSR protection.
12182 *
12183 * Return: 0 for success, error number on failure.
12184 */
12185#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
12186static int wlan_hdd_change_station(struct wiphy *wiphy,
12187 struct net_device *dev,
12188 const u8 *mac,
12189 struct station_parameters *params)
12190#else
12191static int wlan_hdd_change_station(struct wiphy *wiphy,
12192 struct net_device *dev,
12193 u8 *mac,
12194 struct station_parameters *params)
12195#endif
12196{
12197 int ret;
12198
12199 cds_ssr_protect(__func__);
12200 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
12201 cds_ssr_unprotect(__func__);
12202
12203 return ret;
12204}
12205
12206/*
12207 * FUNCTION: __wlan_hdd_cfg80211_add_key
12208 * This function is used to initialize the key information
12209 */
12210static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12211 struct net_device *ndev,
12212 u8 key_index, bool pairwise,
12213 const u8 *mac_addr,
12214 struct key_params *params)
12215{
12216 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12217 tCsrRoamSetKey setKey;
12218 int status;
12219 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012221 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012222 hdd_context_t *pHddCtx;
12223 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12224
12225 ENTER();
12226
Anurag Chouhan6d760662016-02-20 16:05:43 +053012227 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012228 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012229 return -EINVAL;
12230 }
12231
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012232 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012233 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012234 return -EINVAL;
12235 }
12236
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012237 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012238 TRACE_CODE_HDD_CFG80211_ADD_KEY,
12239 pAdapter->sessionId, params->key_len));
12240 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12241 status = wlan_hdd_validate_context(pHddCtx);
12242
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012243 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012244 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012245
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012246 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012247 hdd_device_mode_to_string(pAdapter->device_mode),
12248 pAdapter->device_mode);
12249
12250 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012251 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012252
12253 return -EINVAL;
12254 }
12255
12256 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012257 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012258
12259 return -EINVAL;
12260 }
12261
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012262 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012263
12264 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012265 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012266 setKey.keyId = key_index;
12267 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012268 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012269
12270 switch (params->cipher) {
12271 case WLAN_CIPHER_SUITE_WEP40:
12272 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12273 break;
12274
12275 case WLAN_CIPHER_SUITE_WEP104:
12276 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
12277 break;
12278
12279 case WLAN_CIPHER_SUITE_TKIP:
12280 {
12281 u8 *pKey = &setKey.Key[0];
12282 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
12283
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012284 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012285
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012286 /* Supplicant sends the 32bytes key in this order
12287 *
12288 * |--------------|----------|----------|
12289 * | Tk1 |TX-MIC | RX Mic |
12290 * |--------------|----------|----------|
12291 * <---16bytes---><--8bytes--><--8bytes-->
12292 *
12293 * Sme expects the 32 bytes key to be in the below order
12294 *
12295 * |--------------|----------|----------|
12296 * | Tk1 |RX-MIC | TX Mic |
12297 * |--------------|----------|----------|
12298 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012299 */
12300 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012301 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012302
12303 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012304 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012305
12306 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012307 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012308
12309 break;
12310 }
12311
12312 case WLAN_CIPHER_SUITE_CCMP:
12313 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
12314 break;
12315
12316#ifdef FEATURE_WLAN_WAPI
12317 case WLAN_CIPHER_SUITE_SMS4:
12318 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012319 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
12321 mac_addr, params->key,
12322 params->key_len);
12323 return 0;
12324 }
12325#endif
12326
12327#ifdef FEATURE_WLAN_ESE
12328 case WLAN_CIPHER_SUITE_KRK:
12329 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
12330 break;
12331#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12332 case WLAN_CIPHER_SUITE_BTK:
12333 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
12334 break;
12335#endif
12336#endif
12337
12338#ifdef WLAN_FEATURE_11W
12339 case WLAN_CIPHER_SUITE_AES_CMAC:
12340 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
12341 break;
12342#endif
12343
12344 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012345 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012346 return -EOPNOTSUPP;
12347 }
12348
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012349 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012350
12351 if (!pairwise) {
12352 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012353 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012354 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012355 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012356 } else {
12357 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012358 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012359 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012360 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012361 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012362 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012363 /* if a key is already installed, block all subsequent ones */
12364 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012365 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012366 return 0;
12367 }
12368
12369 setKey.keyDirection = eSIR_TX_RX;
12370 /*Set the group key */
12371 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12372 pAdapter->sessionId, &setKey, &roamId);
12373
12374 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012375 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012376 return -EINVAL;
12377 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012378 /* Save the keys here and call sme_roam_set_key for setting
12379 * the PTK after peer joins the IBSS network
12380 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012381 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012382 &setKey, sizeof(tCsrRoamSetKey));
12383
12384 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
12385 return status;
12386 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012387 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
12388 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012389 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
12390 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070012391 status = wlansap_set_key_sta(
12392 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012393 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012394 hdd_err("wlansap_set_key_sta failed status: %d",
12395 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012396 }
12397 }
12398
12399 /* Save the key in ap ctx for use on START_BASS and restart */
12400 if (pairwise ||
12401 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
12402 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012403 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012404 sizeof(tCsrRoamSetKey));
12405 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012406 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012407 sizeof(tCsrRoamSetKey));
12408
Krunal Sonib4326f22016-03-10 13:05:51 -080012409 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
12410 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012411 hdd_wext_state_t *pWextState =
12412 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12413 hdd_station_ctx_t *pHddStaCtx =
12414 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12415
12416 if (!pairwise) {
12417 /* set group key */
12418 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012419 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012420 __func__, __LINE__);
12421 hdd_perform_roam_set_key_complete(pAdapter);
12422 }
12423 }
12424
12425 pWextState->roamProfile.Keys.KeyLength[key_index] =
12426 (u8) params->key_len;
12427
12428 pWextState->roamProfile.Keys.defaultIndex = key_index;
12429
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012430 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012431 KeyMaterial[key_index][0], params->key,
12432 params->key_len);
12433
12434 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
12435
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012436 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012437 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12438 setKey.keyDirection);
12439
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012440 /* The supplicant may attempt to set the PTK once
12441 * pre-authentication is done. Save the key in the
12442 * UMAC and include it in the ADD BSS request
12443 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012444 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012445 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012446 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012447 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012448 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012449 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012450 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012451 return -EINVAL;
12452 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012453
12454 /* issue set key request to SME */
12455 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12456 pAdapter->sessionId, &setKey, &roamId);
12457
12458 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012459 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012460 pHddStaCtx->roam_info.roamingState =
12461 HDD_ROAM_STATE_NONE;
12462 return -EINVAL;
12463 }
12464
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012465 /* in case of IBSS as there was no information
12466 * available about WEP keys during IBSS join, group
12467 * key intialized with NULL key, so re-initialize
12468 * group key with correct value
12469 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012470 if ((eCSR_BSS_TYPE_START_IBSS ==
12471 pWextState->roamProfile.BSSType)
12472 &&
12473 !((IW_AUTH_KEY_MGMT_802_1X ==
12474 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
12475 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
12476 pHddStaCtx->conn_info.authType)
12477 )
12478 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
12479 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
12480 )
12481 ) {
12482 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012483 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012484
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012485 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012486 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12487 setKey.keyDirection);
12488
12489 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12490 pAdapter->sessionId, &setKey,
12491 &roamId);
12492
12493 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012494 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012495 pHddStaCtx->roam_info.roamingState =
12496 HDD_ROAM_STATE_NONE;
12497 return -EINVAL;
12498 }
12499 }
12500 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012501 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012502 return 0;
12503}
12504
12505static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12506 struct net_device *ndev,
12507 u8 key_index, bool pairwise,
12508 const u8 *mac_addr,
12509 struct key_params *params)
12510{
12511 int ret;
12512 cds_ssr_protect(__func__);
12513 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
12514 mac_addr, params);
12515 cds_ssr_unprotect(__func__);
12516
12517 return ret;
12518}
12519
12520/*
12521 * FUNCTION: __wlan_hdd_cfg80211_get_key
12522 * This function is used to get the key information
12523 */
12524static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12525 struct net_device *ndev,
12526 u8 key_index, bool pairwise,
12527 const u8 *mac_addr, void *cookie,
12528 void (*callback)(void *cookie,
12529 struct key_params *)
12530 )
12531{
12532 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12533 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12534 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
12535 struct key_params params;
12536
12537 ENTER();
12538
Anurag Chouhan6d760662016-02-20 16:05:43 +053012539 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012540 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012541 return -EINVAL;
12542 }
12543
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012544 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012545 hdd_device_mode_to_string(pAdapter->device_mode),
12546 pAdapter->device_mode);
12547
12548 memset(&params, 0, sizeof(params));
12549
12550 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012551 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012552 return -EINVAL;
12553 }
12554
12555 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12556 case eCSR_ENCRYPT_TYPE_NONE:
12557 params.cipher = IW_AUTH_CIPHER_NONE;
12558 break;
12559
12560 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12561 case eCSR_ENCRYPT_TYPE_WEP40:
12562 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12563 break;
12564
12565 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12566 case eCSR_ENCRYPT_TYPE_WEP104:
12567 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12568 break;
12569
12570 case eCSR_ENCRYPT_TYPE_TKIP:
12571 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12572 break;
12573
12574 case eCSR_ENCRYPT_TYPE_AES:
12575 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12576 break;
12577
12578 default:
12579 params.cipher = IW_AUTH_CIPHER_NONE;
12580 break;
12581 }
12582
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012583 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012584 TRACE_CODE_HDD_CFG80211_GET_KEY,
12585 pAdapter->sessionId, params.cipher));
12586
12587 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12588 params.seq_len = 0;
12589 params.seq = NULL;
12590 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12591 callback(cookie, &params);
12592
12593 EXIT();
12594 return 0;
12595}
12596
12597static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12598 struct net_device *ndev,
12599 u8 key_index, bool pairwise,
12600 const u8 *mac_addr, void *cookie,
12601 void (*callback)(void *cookie,
12602 struct key_params *)
12603 )
12604{
12605 int ret;
12606
12607 cds_ssr_protect(__func__);
12608 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12609 mac_addr, cookie, callback);
12610 cds_ssr_unprotect(__func__);
12611
12612 return ret;
12613}
12614
12615/**
12616 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12617 * @wiphy: wiphy interface context
12618 * @ndev: pointer to net device
12619 * @key_index: Key index used in 802.11 frames
12620 * @unicast: true if it is unicast key
12621 * @multicast: true if it is multicast key
12622 *
12623 * This function is required for cfg80211_ops API.
12624 * It is used to delete the key information
12625 * Underlying hardware implementation does not have API to delete the
12626 * encryption key. It is automatically deleted when the peer is
12627 * removed. Hence this function currently does nothing.
12628 * Future implementation may interprete delete key operation to
12629 * replacing the key with a random junk value, effectively making it
12630 * useless.
12631 *
12632 * Return: status code, always 0.
12633 */
12634
12635static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12636 struct net_device *ndev,
12637 u8 key_index,
12638 bool pairwise, const u8 *mac_addr)
12639{
12640 EXIT();
12641 return 0;
12642}
12643
12644/**
12645 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12646 * @wiphy: Pointer to wiphy structure.
12647 * @dev: Pointer to net_device structure.
12648 * @key_index: key index
12649 * @pairwise: pairwise
12650 * @mac_addr: mac address
12651 *
12652 * This is the cfg80211 delete key handler function which invokes
12653 * the internal function @__wlan_hdd_cfg80211_del_key with
12654 * SSR protection.
12655 *
12656 * Return: 0 for success, error number on failure.
12657 */
12658static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12659 struct net_device *dev,
12660 u8 key_index,
12661 bool pairwise, const u8 *mac_addr)
12662{
12663 int ret;
12664
12665 cds_ssr_protect(__func__);
12666 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12667 pairwise, mac_addr);
12668 cds_ssr_unprotect(__func__);
12669
12670 return ret;
12671}
12672
12673/*
12674 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12675 * This function is used to set the default tx key index
12676 */
12677static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12678 struct net_device *ndev,
12679 u8 key_index,
12680 bool unicast, bool multicast)
12681{
12682 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12683 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12684 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12685 hdd_context_t *pHddCtx;
12686 int status;
12687
12688 ENTER();
12689
Anurag Chouhan6d760662016-02-20 16:05:43 +053012690 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012691 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012692 return -EINVAL;
12693 }
12694
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012695 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012696 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012697 return -EINVAL;
12698 }
12699
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012700 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012701 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12702 pAdapter->sessionId, key_index));
12703
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012704 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012705 hdd_device_mode_to_string(pAdapter->device_mode),
12706 pAdapter->device_mode, key_index);
12707
12708 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012709 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710 return -EINVAL;
12711 }
12712
12713 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12714 status = wlan_hdd_validate_context(pHddCtx);
12715
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012716 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012717 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718
Krunal Sonib4326f22016-03-10 13:05:51 -080012719 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12720 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012721 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12722 pHddStaCtx->conn_info.ucEncryptionType) &&
12723 (eCSR_ENCRYPT_TYPE_AES !=
12724 pHddStaCtx->conn_info.ucEncryptionType)) {
12725 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012726 * then update the default key index
12727 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012728
12729 tCsrRoamSetKey setKey;
12730 uint32_t roamId = 0xFF;
12731 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12732
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012733 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012734
12735 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012736 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012737 setKey.keyId = key_index;
12738 setKey.keyLength = Keys->KeyLength[key_index];
12739
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012740 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012741 &Keys->KeyMaterial[key_index][0],
12742 Keys->KeyLength[key_index]);
12743
12744 setKey.keyDirection = eSIR_TX_RX;
12745
Anurag Chouhanc5548422016-02-24 18:33:27 +053012746 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012747 &pHddStaCtx->conn_info.bssId);
12748
12749 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12750 pWextState->roamProfile.EncryptionType.
12751 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012752 /* In the case of dynamic wep
12753 * supplicant hardcodes DWEP type to
12754 * eCSR_ENCRYPT_TYPE_WEP104 even
12755 * though ap is configured for WEP-40
12756 * encryption. In this canse the key
12757 * length is 5 but the encryption type
12758 * is 104 hence checking the key
12759 * lenght(5) and encryption type(104)
12760 * and switching encryption type to 40
12761 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012762 pWextState->roamProfile.EncryptionType.
12763 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12764 pWextState->roamProfile.mcEncryptionType.
12765 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12766 }
12767
12768 setKey.encType =
12769 pWextState->roamProfile.EncryptionType.
12770 encryptionType[0];
12771
12772 /* Issue set key request */
12773 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12774 pAdapter->sessionId, &setKey,
12775 &roamId);
12776
12777 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012778 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012779 status);
12780 return -EINVAL;
12781 }
12782 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012783 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012784 /* In SoftAp mode setting key direction for default mode */
12785 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12786 pWextState->roamProfile.EncryptionType.encryptionType[0])
12787 && (eCSR_ENCRYPT_TYPE_AES !=
12788 pWextState->roamProfile.EncryptionType.
12789 encryptionType[0])) {
12790 /* Saving key direction for default key index to TX default */
12791 hdd_ap_ctx_t *pAPCtx =
12792 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12793 pAPCtx->wepKey[key_index].keyDirection =
12794 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012795 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012796 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012797 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012798 }
12799 }
12800
12801 EXIT();
12802 return status;
12803}
12804
12805static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12806 struct net_device *ndev,
12807 u8 key_index,
12808 bool unicast, bool multicast)
12809{
12810 int ret;
12811 cds_ssr_protect(__func__);
12812 ret =
12813 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12814 multicast);
12815 cds_ssr_unprotect(__func__);
12816
12817 return ret;
12818}
12819
Abhishek Singhc9941602016-08-09 16:06:22 +053012820/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012821 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12822 * interface that BSS might have been lost.
12823 * @pAdapter: adaptor
12824 * @bssid: bssid which might have been lost
12825 *
12826 * Return: bss which is unlinked from kernel cache
12827 */
12828struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12829 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012830{
12831 struct net_device *dev = pAdapter->dev;
12832 struct wireless_dev *wdev = dev->ieee80211_ptr;
12833 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012834 struct cfg80211_bss *bss = NULL;
12835
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012836 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012837 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012838 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012839 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012840 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012841 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012842 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012843 cfg80211_unlink_bss(wiphy, bss);
12844 }
12845 return bss;
12846}
12847
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012848#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12849 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12850static struct cfg80211_bss *
12851wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12852 struct ieee80211_channel *chan,
12853 struct ieee80211_mgmt *mgmt,
12854 size_t frame_len,
12855 int rssi, gfp_t gfp,
12856 uint64_t boottime_ns)
12857{
12858 struct cfg80211_bss *bss_status = NULL;
12859 struct cfg80211_inform_bss data = {0};
12860
12861 data.chan = chan;
12862 data.boottime_ns = boottime_ns;
12863 data.signal = rssi;
12864 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12865 frame_len, gfp);
12866 return bss_status;
12867}
12868#else
12869static struct cfg80211_bss *
12870wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12871 struct ieee80211_channel *chan,
12872 struct ieee80211_mgmt *mgmt,
12873 size_t frame_len,
12874 int rssi, gfp_t gfp,
12875 uint64_t boottime_ns)
12876{
12877 struct cfg80211_bss *bss_status = NULL;
12878
12879 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12880 rssi, gfp);
12881 return bss_status;
12882}
12883#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012884
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012885/**
12886 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12887 * @pAdapter: Pointer to adapter
12888 * @bss_desc: Pointer to bss descriptor
12889 *
12890 * This function is used to inform the BSS details to nl80211 interface.
12891 *
12892 * Return: struct cfg80211_bss pointer
12893 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012894struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12895 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012896{
12897 /*
12898 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12899 * already exists in bss data base of cfg80211 for that particular BSS
12900 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12901 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12902 * As of now there is no possibility to get the mgmt(probe response)
12903 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12904 * and passing to cfg80211_inform_bss_frame.
12905 */
12906 struct net_device *dev = pAdapter->dev;
12907 struct wireless_dev *wdev = dev->ieee80211_ptr;
12908 struct wiphy *wiphy = wdev->wiphy;
12909 int chan_no = bss_desc->channelId;
12910#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12911 qcom_ie_age *qie_age = NULL;
12912 int ie_length =
12913 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12914#else
12915 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12916#endif
12917 const char *ie =
12918 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12919 unsigned int freq;
12920 struct ieee80211_channel *chan;
12921 struct ieee80211_mgmt *mgmt = NULL;
12922 struct cfg80211_bss *bss_status = NULL;
12923 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12924 int rssi = 0;
12925 hdd_context_t *pHddCtx;
12926 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012927 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012928 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012929
12930 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12931 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012932 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012933 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012934
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012935 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012936 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012937 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012938 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012939 return NULL;
12940 }
12941
12942 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12943
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012944 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012945 * Instead it wants a monotonic increasing value
12946 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012947 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012948 mgmt->u.probe_resp.timestamp =
12949 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012950
12951 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12952 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12953
12954#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12955 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12956 /* Assuming this is the last IE, copy at the end */
12957 ie_length -= sizeof(qcom_ie_age);
12958 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12959 qie_age->element_id = QCOM_VENDOR_IE_ID;
12960 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12961 qie_age->oui_1 = QCOM_OUI1;
12962 qie_age->oui_2 = QCOM_OUI2;
12963 qie_age->oui_3 = QCOM_OUI3;
12964 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012965 /*
12966 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12967 * all bss related timestamp is in units of ms. Due to this when scan
12968 * results are sent to lowi the scan age is high.To address this,
12969 * send age in units of 1/10 ms.
12970 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012972 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012973 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012974 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12975 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012976 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12977 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012978#endif
12979
12980 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12981 if (bss_desc->fProbeRsp) {
12982 mgmt->frame_control |=
12983 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12984 } else {
12985 mgmt->frame_control |=
12986 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12987 }
12988
12989 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012990 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012991 freq =
12992 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012993 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012994 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012995 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012996 freq =
12997 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012998 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012999 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013000 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070013001 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013002 return NULL;
13003 }
13004
13005 chan = __ieee80211_get_channel(wiphy, freq);
13006 /* When the band is changed on the fly using the GUI, three things are done
13007 * 1. scan abort
13008 * 2. flush scan results from cache
13009 * 3. update the band with the new band user specified (refer to the
13010 * hdd_set_band_helper function) as part of the scan abort, message will be
13011 * queued to PE and we proceed with flushing and changinh the band.
13012 * PE will stop the scanning further and report back the results what ever
13013 * it had till now by calling the call back function.
13014 * if the time between update band and scandone call back is sufficient
13015 * enough the band change reflects in SME, SME validates the channels
13016 * and discards the channels correponding to previous band and calls back
13017 * with zero bss results. but if the time between band update and scan done
13018 * callback is very small then band change will not reflect in SME and SME
13019 * reports to HDD all the channels correponding to previous band.this is due
13020 * to race condition.but those channels are invalid to the new band and so
13021 * this function __ieee80211_get_channel will return NULL.Each time we
13022 * report scan result with this pointer null warning kernel trace is printed.
13023 * if the scan results contain large number of APs continuosly kernel
13024 * warning trace is printed and it will lead to apps watch dog bark.
13025 * So drop the bss and continue to next bss.
13026 */
13027 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053013028 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
13029 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070013030 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013031 return NULL;
13032 }
13033
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070013034 /* Based on .ini configuration, raw rssi can be reported for bss.
13035 * Raw rssi is typically used for estimating power.
13036 */
13037
13038 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
13039 bss_desc->rssi;
13040
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013041 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053013042 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013043
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080013044 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013045 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070013046 (int)(rssi / 100),
13047 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013048
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053013049 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
13050 frame_len, rssi,
13051 GFP_KERNEL,
13052 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053013053 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070013054 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013055 return bss_status;
13056}
13057
13058/**
13059 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
13060 * @pAdapter: Pointer to adapter
13061 * @pRoamInfo: Pointer to roam info
13062 *
13063 * This function is used to update the BSS data base of CFG8011
13064 *
13065 * Return: struct cfg80211_bss pointer
13066 */
13067struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
13068 tCsrRoamInfo *pRoamInfo)
13069{
13070 tCsrRoamConnectedProfile roamProfile;
13071 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13072 struct cfg80211_bss *bss = NULL;
13073
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013074 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
13075 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
13076
13077 if (NULL != roamProfile.pBssDesc) {
13078 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
13079 roamProfile.pBssDesc);
13080
13081 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013082 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013083
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080013084 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013085 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013086 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013087 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013088 return bss;
13089}
13090/**
13091 * wlan_hdd_cfg80211_update_bss() - update bss
13092 * @wiphy: Pointer to wiphy
13093 * @pAdapter: Pointer to adapter
13094 * @scan_time: scan request timestamp
13095 *
13096 * Return: zero if success, non-zero otherwise
13097 */
13098int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
13099 hdd_adapter_t *pAdapter,
13100 uint32_t scan_time)
13101{
13102 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13103 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013104 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013105 tScanResultHandle pResult;
13106 struct cfg80211_bss *bss_status = NULL;
13107 hdd_context_t *pHddCtx;
13108 int ret;
13109
13110 ENTER();
13111
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013112 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13113 hdd_err("invalid session id: %d", pAdapter->sessionId);
13114 return -EINVAL;
13115 }
13116
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013117 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
13119 NO_SESSION, pAdapter->sessionId));
13120
13121 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13122 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013123 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013124 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013125
13126 /* start getting scan results and populate cgf80211 BSS database */
13127 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
13128
13129 /* no scan results */
13130 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013131 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053013132 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013133 }
13134
13135 pScanResult = sme_scan_result_get_first(hHal, pResult);
13136
13137 while (pScanResult) {
13138 /*
13139 * - cfg80211_inform_bss() is not updating ie field of bss
13140 * entry if entry already exists in bss data base of cfg80211
13141 * for that particular BSS ID. Using cfg80211_inform_bss_frame
13142 * to update thebss entry instead of cfg80211_inform_bss,
13143 * But this call expects mgmt packet as input. As of now
13144 * there is no possibility to get the mgmt(probe response)
13145 * frame from PE, converting bss_desc to
13146 * ieee80211_mgmt(probe response) and passing to c
13147 * fg80211_inform_bss_frame.
13148 * - Update BSS only if beacon timestamp is later than
13149 * scan request timestamp.
13150 */
13151 if ((scan_time == 0) ||
13152 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053013153 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013154 bss_status =
13155 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
13156 &pScanResult->BssDescriptor);
13157
13158 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013159 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013160 } else {
13161 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013162 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013163 bss_status);
13164 }
13165 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013166 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013167 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
13168 }
13169 pScanResult = sme_scan_result_get_next(hHal, pResult);
13170 }
13171
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070013172 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013173 /*
13174 * For SAP mode, scan is invoked by hostapd during SAP start
13175 * if hostapd is restarted, we need to flush previous scan
13176 * result so that it will reflect environment change
13177 */
Krunal Sonib4326f22016-03-10 13:05:51 -080013178 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013179#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
13180 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
13181#endif
13182 )
13183 sme_scan_flush_result(hHal);
13184
13185 EXIT();
13186 return 0;
13187}
13188
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013189/**
13190 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
13191 * @pAdapter: Pointer to adapter
13192 * @pRoamInfo: Pointer to roam info
13193 * @index: Index
13194 * @preauth: Preauth flag
13195 *
13196 * This function is used to notify the supplicant of a new PMKSA candidate.
13197 *
13198 * Return: 0 for success, non-zero for failure
13199 */
13200int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
13201 tCsrRoamInfo *pRoamInfo,
13202 int index, bool preauth)
13203{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204 struct net_device *dev = pAdapter->dev;
13205 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
13206
13207 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013208 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013209
13210 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013211 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013212 return -EINVAL;
13213 }
13214
13215 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013216 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013217 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
13218 cfg80211_pmksa_candidate_notify(dev, index,
13219 pRoamInfo->bssid.bytes,
13220 preauth, GFP_KERNEL);
13221 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013222 return 0;
13223}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013224
13225#ifdef FEATURE_WLAN_LFR_METRICS
13226/**
13227 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
13228 * @pAdapter: Pointer to adapter
13229 * @pRoamInfo: Pointer to roam info
13230 *
13231 * 802.11r/LFR metrics reporting function to report preauth initiation
13232 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013233 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013234 */
13235#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013236QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013237 tCsrRoamInfo *pRoamInfo)
13238{
13239 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13240 union iwreq_data wrqu;
13241
13242 ENTER();
13243
13244 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013245 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013246 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013247 }
13248
13249 /* create the event */
13250 memset(&wrqu, 0, sizeof(wrqu));
13251 memset(metrics_notification, 0, sizeof(metrics_notification));
13252
13253 wrqu.data.pointer = metrics_notification;
13254 wrqu.data.length = scnprintf(metrics_notification,
13255 sizeof(metrics_notification),
13256 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013257 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258
13259 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13260 metrics_notification);
13261
13262 EXIT();
13263
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013264 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013265}
13266
13267/**
13268 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13269 * @pAdapter: Pointer to adapter
13270 * @pRoamInfo: Pointer to roam info
13271 * @preauth_status: Preauth status
13272 *
13273 * 802.11r/LFR metrics reporting function to report handover initiation
13274 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013275 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013276 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013277QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013278wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
13279 tCsrRoamInfo *pRoamInfo,
13280 bool preauth_status)
13281{
13282 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13283 union iwreq_data wrqu;
13284
13285 ENTER();
13286
13287 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013288 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013289 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013290 }
13291
13292 /* create the event */
13293 memset(&wrqu, 0, sizeof(wrqu));
13294 memset(metrics_notification, 0, sizeof(metrics_notification));
13295
13296 scnprintf(metrics_notification, sizeof(metrics_notification),
13297 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013298 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013299
13300 if (1 == preauth_status)
13301 strlcat(metrics_notification, " true",
13302 sizeof(metrics_notification));
13303 else
13304 strlcat(metrics_notification, " false",
13305 sizeof(metrics_notification));
13306
13307 wrqu.data.pointer = metrics_notification;
13308 wrqu.data.length = strlen(metrics_notification);
13309
13310 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13311 metrics_notification);
13312
13313 EXIT();
13314
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013315 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013316}
13317
13318/**
13319 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13320 * @pAdapter: Pointer to adapter
13321 * @pRoamInfo: Pointer to roam info
13322 *
13323 * 802.11r/LFR metrics reporting function to report handover initiation
13324 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013325 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013326 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013327QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013328 tCsrRoamInfo *pRoamInfo)
13329{
13330 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13331 union iwreq_data wrqu;
13332
13333 ENTER();
13334
13335 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013336 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013337 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338 }
13339
13340 /* create the event */
13341 memset(&wrqu, 0, sizeof(wrqu));
13342 memset(metrics_notification, 0, sizeof(metrics_notification));
13343
13344 wrqu.data.pointer = metrics_notification;
13345 wrqu.data.length = scnprintf(metrics_notification,
13346 sizeof(metrics_notification),
13347 "QCOM: LFR_PREAUTH_HANDOVER "
13348 MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013349 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013350
13351 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13352 metrics_notification);
13353
13354 EXIT();
13355
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013356 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013357}
13358#endif
13359
13360/**
13361 * hdd_select_cbmode() - select channel bonding mode
13362 * @pAdapter: Pointer to adapter
13363 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013364 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013365 *
13366 * Return: none
13367 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013368void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080013369 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013370{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013371 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013372 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013373 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013374 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013375
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013376 /*
13377 * CDS api expects secondary channel for calculating
13378 * the channel params
13379 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013380 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013381 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013382 if (operationChannel >= 1 && operationChannel <= 5)
13383 sec_ch = operationChannel + 4;
13384 else if (operationChannel >= 6 && operationChannel <= 13)
13385 sec_ch = operationChannel - 4;
13386 }
13387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013388 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013389 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
13390 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013391
13392 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070013393 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013394 uint8_t iniDot11Mode =
13395 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
13396
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013397 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013398 switch (iniDot11Mode) {
13399 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080013400 case eHDD_DOT11_MODE_11ax:
13401 case eHDD_DOT11_MODE_11ax_ONLY:
13402 if (sme_is_feature_supported_by_fw(DOT11AX))
13403 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
13404 else if (sme_is_feature_supported_by_fw(DOT11AC))
13405 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13406 else
13407 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13408 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013409 case eHDD_DOT11_MODE_11ac:
13410 case eHDD_DOT11_MODE_11ac_ONLY:
13411 if (sme_is_feature_supported_by_fw(DOT11AC))
13412 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13413 else
13414 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13415 break;
13416 case eHDD_DOT11_MODE_11n:
13417 case eHDD_DOT11_MODE_11n_ONLY:
13418 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13419 break;
13420 default:
13421 hdd_dot11_mode = iniDot11Mode;
13422 break;
13423 }
13424 ch_info->channel_width = ch_params->ch_width;
13425 ch_info->phy_mode =
13426 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013427 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013428 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013429 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013430 ch_info->channel_width, ch_info->phy_mode,
13431 ch_info->channel);
13432 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013433}
13434
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013435/**
13436 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
13437 * @adapter: STA adapter
13438 * @roam_profile: STA roam profile
13439 *
13440 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
13441 *
13442 * Return: false if sta-sap conc is not allowed, else return true
13443 */
13444static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
13445 tCsrRoamProfile *roam_profile)
13446{
13447 hdd_context_t *hdd_ctx;
13448 hdd_adapter_t *ap_adapter;
13449 hdd_ap_ctx_t *hdd_ap_ctx;
13450 hdd_hostapd_state_t *hostapd_state;
13451 uint8_t channel = 0;
13452 QDF_STATUS status;
13453
13454 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13455 if (!hdd_ctx) {
13456 hdd_err("HDD context is NULL");
13457 return true;
13458 }
13459
13460 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
13461 /* probably no sap running, no handling required */
13462 if (ap_adapter == NULL)
13463 return true;
13464
13465 /*
13466 * sap is not in started state, so it is fine to go ahead with sta.
13467 * if sap is currently doing CAC then don't allow sta to go further.
13468 */
13469 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
13470 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
13471 return true;
13472
13473 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
13474 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
13475 return false;
13476 }
13477
13478 /*
13479 * log and return error, if we allow STA to go through, we don't
13480 * know what is going to happen better stop sta connection
13481 */
13482 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
13483 if (NULL == hdd_ap_ctx) {
13484 hdd_err("AP context not found");
13485 return false;
13486 }
13487
13488 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013489 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
13490 hdd_ap_ctx->operatingChannel)) {
13491 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013492 return true;
13493 }
13494 /*
13495 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053013496 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013497 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013498 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013499 roam_profile, &channel);
13500
Nitesh Shah59774522016-09-16 15:14:21 +053013501 /*
13502 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
13503 * channels for roaming case.
13504 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013505 if (WLAN_REG_IS_24GHZ_CH(channel)) {
13506 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053013507 return true;
13508 }
13509
13510 /*
13511 * If channel is 0 or DFS then better to call pcl and find out the
13512 * best channel. If channel is non-dfs 5 GHz then better move SAP
13513 * to STA's channel to make scc, so we have room for 3port MCC
13514 * scenario.
13515 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013516 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013517 channel = policy_mgr_get_nondfs_preferred_channel(
13518 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013519
13520 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
13521 qdf_event_reset(&hostapd_state->qdf_event);
13522 status = wlansap_set_channel_change_with_csa(
13523 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
13524 hdd_ap_ctx->sapConfig.ch_width_orig);
13525
13526 if (QDF_STATUS_SUCCESS != status) {
13527 hdd_err("Set channel with CSA IE failed, can't allow STA");
13528 return false;
13529 }
13530
13531 /*
13532 * wait here for SAP to finish the channel switch. When channel
13533 * switch happens, SAP sends few beacons with CSA_IE. After
13534 * successfully Transmission of those beacons, it will move its
13535 * state from started to disconnected and move to new channel.
13536 * once it moves to new channel, sap again moves its state
13537 * machine from disconnected to started and set this event.
13538 * wait for 10 secs to finish this.
13539 */
13540 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
13541 if (!QDF_IS_STATUS_SUCCESS(status)) {
13542 hdd_err("wait for qdf_event failed, STA not allowed!!");
13543 return false;
13544 }
13545
13546 return true;
13547}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013548
Abhishek Singhcfb44482017-03-10 12:42:37 +053013549#ifdef WLAN_FEATURE_11W
13550/**
13551 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13552 * @roam_profile: pointer to roam profile
13553 *
13554 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13555 * or pmf=2 is an explicit configuration in the supplicant
13556 * configuration, drop the connection request.
13557 *
13558 * Return: 0 if check result is valid, otherwise return error code
13559 */
13560static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13561{
13562 if (roam_profile->MFPEnabled &&
13563 !(roam_profile->MFPRequired ||
13564 roam_profile->MFPCapable)) {
13565 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13566 roam_profile->MFPEnabled,
13567 roam_profile->MFPRequired,
13568 roam_profile->MFPCapable);
13569 return -EINVAL;
13570 }
13571 return 0;
13572}
13573#else
13574static inline
13575int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13576{
13577 return 0;
13578}
13579#endif
13580
Krunal Soni31949422016-07-29 17:17:53 -070013581/**
13582 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013583 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013584 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013585 * @ssid_len: Length of ssid
13586 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013587 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013588 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013589 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013590 *
13591 * This function is used to start the association process
13592 *
13593 * Return: 0 for success, non-zero for failure
13594 */
Krunal Soni31949422016-07-29 17:17:53 -070013595static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013596 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013597 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013598 u8 operatingChannel,
13599 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013600{
13601 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013602 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013603 hdd_wext_state_t *pWextState;
13604 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013605 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013606 uint32_t roamId;
13607 tCsrRoamProfile *pRoamProfile;
13608 eCsrAuthType RSNAuthType;
13609 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013610 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013611
13612 ENTER();
13613
13614 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13615 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013616 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617
13618 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013619 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013620 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013621
13622 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013623 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013624 status = -EINVAL;
13625 goto ret_status;
13626 }
13627
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013628 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013629 hdd_err("Connection refused: conn in progress");
13630 status = -EINVAL;
13631 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013632 }
13633
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013634 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013635 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13636
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013637 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013638 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13639 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013640
13641 if (pRoamProfile) {
13642 hdd_station_ctx_t *pHddStaCtx;
13643 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13644
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013645 /* Restart the opportunistic timer
13646 *
13647 * If hw_mode_change_in_progress is true, then wait
13648 * till firmware sends the callback for hw_mode change.
13649 *
13650 * Else set connect_in_progress as true and proceed.
13651 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013652 policy_mgr_restart_opportunistic_timer(
13653 pHddCtx->hdd_psoc, false);
13654 if (policy_mgr_is_hw_mode_change_in_progress(
13655 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013656 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013657 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013658 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013659 hdd_err("qdf wait for event failed!!");
13660 status = -EINVAL;
13661 goto ret_status;
13662 }
13663 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013664 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013665
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013666 if (HDD_WMM_USER_MODE_NO_QOS ==
13667 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13668 /*QoS not enabled in cfg file */
13669 pRoamProfile->uapsd_mask = 0;
13670 } else {
13671 /*QoS enabled, update uapsd mask from cfg file */
13672 pRoamProfile->uapsd_mask =
13673 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13674 }
13675
13676 pRoamProfile->SSIDs.numOfSSIDs = 1;
13677 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013678 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013679 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013680 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013681 ssid, ssid_len);
13682
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013683 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013684 /* cleanup bssid hint */
13685 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13686 QDF_MAC_ADDR_SIZE);
13687 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13688 QDF_MAC_ADDR_SIZE);
13689
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013690 if (bssid) {
13691 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013692 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013693 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013694 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013695 /*
13696 * Save BSSID in seperate variable as
13697 * pRoamProfile's BSSID is getting zeroed out in the
13698 * association process. In case of join failure
13699 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013700 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013701 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013702 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013703 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013704 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013705 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13706 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013707 /*
13708 * Save BSSID in a separate variable as
13709 * pRoamProfile's BSSID is getting zeroed out in the
13710 * association process. In case of join failure
13711 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013712 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013713 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013714 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013715 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013716 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013717 }
13718
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013719 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013720 pRoamProfile->SSIDs.SSIDList->SSID.length,
13721 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13722 operatingChannel);
13723
13724 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13725 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013726 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013727 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13728 }
13729#ifdef FEATURE_WLAN_WAPI
13730 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013731 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013732 switch (pAdapter->wapi_info.wapiAuthMode) {
13733 case WAPI_AUTH_MODE_PSK:
13734 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013735 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013736 pAdapter->wapi_info.wapiAuthMode);
13737 pRoamProfile->AuthType.authType[0] =
13738 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13739 break;
13740 }
13741 case WAPI_AUTH_MODE_CERT:
13742 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013743 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744 pAdapter->wapi_info.wapiAuthMode);
13745 pRoamProfile->AuthType.authType[0] =
13746 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13747 break;
13748 }
13749 } /* End of switch */
13750 if (pAdapter->wapi_info.wapiAuthMode ==
13751 WAPI_AUTH_MODE_PSK
13752 || pAdapter->wapi_info.wapiAuthMode ==
13753 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013754 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013755 pRoamProfile->AuthType.numEntries = 1;
13756 pRoamProfile->EncryptionType.numEntries = 1;
13757 pRoamProfile->EncryptionType.encryptionType[0] =
13758 eCSR_ENCRYPT_TYPE_WPI;
13759 pRoamProfile->mcEncryptionType.numEntries = 1;
13760 pRoamProfile->mcEncryptionType.
13761 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13762 }
13763 }
Krunal Soni31949422016-07-29 17:17:53 -070013764#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013765 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013766 pRoamProfile->csrPersona = pAdapter->device_mode;
13767
13768 if (operatingChannel) {
13769 pRoamProfile->ChannelInfo.ChannelList =
13770 &operatingChannel;
13771 pRoamProfile->ChannelInfo.numOfChannels = 1;
13772 } else {
13773 pRoamProfile->ChannelInfo.ChannelList = NULL;
13774 pRoamProfile->ChannelInfo.numOfChannels = 0;
13775 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013776 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013777 && operatingChannel) {
13778 /*
13779 * Need to post the IBSS power save parameters
13780 * to WMA. WMA will configure this parameters
13781 * to firmware if power save is enabled by the
13782 * firmware.
13783 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013784 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013785
Abhishek Singh471652b2017-04-14 12:28:32 +053013786 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013787 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013788 status = -EINVAL;
13789 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013790 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013791 pRoamProfile->ch_params.ch_width =
13792 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013793 /*
13794 * In IBSS mode while operating in 2.4 GHz,
13795 * the device supports only 20 MHz.
13796 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013797 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013798 pRoamProfile->ch_params.ch_width =
13799 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013800 hdd_select_cbmode(pAdapter, operatingChannel,
13801 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013802 }
13803
Abhishek Singhcfb44482017-03-10 12:42:37 +053013804 if (wlan_hdd_cfg80211_check_pmf_valid(
13805 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013806 status = -EINVAL;
13807 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013808 }
13809
Krunal Soni31949422016-07-29 17:17:53 -070013810 /*
13811 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013812 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013813 * enhancements, the supplicant is not issuing the scan command
13814 * now. So the unicast frames which are sent from the host are
13815 * not having the additional IEs. If it is P2P CLIENT and there
13816 * is no additional IE present in roamProfile, then use the
13817 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013818 */
13819
Krunal Sonib4326f22016-03-10 13:05:51 -080013820 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013821 (!pRoamProfile->pAddIEScan)) {
13822 pRoamProfile->pAddIEScan =
13823 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13824 pRoamProfile->nAddIEScanLength =
13825 pAdapter->scan_info.scanAddIE.length;
13826 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013827
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013828 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13829 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013830 pRoamProfile))) {
13831 hdd_err("sap-sta conc will fail, can't allow sta");
13832 hdd_conn_set_connection_state(pAdapter,
13833 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013834 status = -ENOMEM;
13835 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013836 }
13837
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013838 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013839 if (!sme_config) {
13840 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013841 hdd_conn_set_connection_state(pAdapter,
13842 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013843 status = -ENOMEM;
13844 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013845 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013846 sme_get_config_param(pHddCtx->hHal, sme_config);
13847 /* These values are not sessionized. So, any change in these SME
13848 * configs on an older or parallel interface will affect the
13849 * cb mode. So, restoring the default INI params before starting
13850 * interfaces such as sta, cli etc.,
13851 */
13852 sme_config->csrConfig.channelBondingMode5GHz =
13853 pHddCtx->config->nChannelBondingMode5GHz;
13854 sme_config->csrConfig.channelBondingMode24GHz =
13855 pHddCtx->config->nChannelBondingMode24GHz;
13856 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013857 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013858 /*
13859 * Change conn_state to connecting before sme_roam_connect(),
13860 * because sme_roam_connect() has a direct path to call
13861 * hdd_sme_roam_callback(), which will change the conn_state
13862 * If direct path, conn_state will be accordingly changed to
13863 * NotConnected or Associated by either
13864 * hdd_association_completion_handler() or
13865 * hdd_dis_connect_handler() in sme_RoamCallback()if
13866 * sme_RomConnect is to be queued,
13867 * Connecting state will remain until it is completed.
13868 *
13869 * If connection state is not changed, connection state will
13870 * remain in eConnectionState_NotConnected state.
13871 * In hdd_association_completion_handler, "hddDisconInProgress"
13872 * is set to true if conn state is
13873 * eConnectionState_NotConnected.
13874 * If "hddDisconInProgress" is set to true then cfg80211 layer
13875 * is not informed of connect result indication which
13876 * is an issue.
13877 */
13878 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013879 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013880 hdd_conn_set_connection_state(pAdapter,
13881 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013882
Komal Seelama89be8d2016-09-29 11:09:26 +053013883 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13884 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013885 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013886 pAdapter->sessionId, pRoamProfile,
13887 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013888 if (QDF_IS_STATUS_ERROR(qdf_status))
13889 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013890
Rajeev Kumard31e1542017-01-13 14:37:42 -080013891 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013892 (QDF_STA_MODE == pAdapter->device_mode ||
13893 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013894 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013895 "qdf_status %d. -> NotConnected",
13896 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013897 /* change back to NotAssociated */
13898 hdd_conn_set_connection_state(pAdapter,
13899 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013900 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13901 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013902 }
13903
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013904 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013905 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013907 pRoamProfile->ChannelInfo.ChannelList = NULL;
13908 pRoamProfile->ChannelInfo.numOfChannels = 0;
13909
Nitesh Shah044fd672016-10-13 18:53:25 +053013910 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013911 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13912 && !policy_mgr_is_hw_dbs_2x2_capable(
13913 pHddCtx->hdd_psoc)) {
13914 policy_mgr_get_channel_from_scan_result(
13915 pHddCtx->hdd_psoc,
13916 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013917 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013918 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013919 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13920 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013921 }
13922
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013923 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013924 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013925 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013926 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013927 goto ret_status;
13928
13929conn_failure:
13930 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013931 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013932
13933ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013934 EXIT();
13935 return status;
13936}
13937
13938/**
13939 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13940 * @pAdapter: Pointer to adapter
13941 * @auth_type: Auth type
13942 *
13943 * This function is used to set the authentication type (OPEN/SHARED).
13944 *
13945 * Return: 0 for success, non-zero for failure
13946 */
13947static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13948 enum nl80211_auth_type auth_type)
13949{
13950 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13951 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13952
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 /*set authentication type */
13954 switch (auth_type) {
13955 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013956 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013957 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13958 break;
13959
13960 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013961 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013962 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013963 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13964 break;
13965
13966 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013967 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013968 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13969 break;
13970#ifdef FEATURE_WLAN_ESE
13971 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013972 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013973 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13974 break;
13975#endif
13976
13977 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013978 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13980 return -EINVAL;
13981 }
13982
13983 pWextState->roamProfile.AuthType.authType[0] =
13984 pHddStaCtx->conn_info.authType;
13985 return 0;
13986}
13987
13988/**
13989 * wlan_hdd_set_akm_suite() - set key management type
13990 * @pAdapter: Pointer to adapter
13991 * @key_mgmt: Key management type
13992 *
13993 * This function is used to set the key mgmt type(PSK/8021x).
13994 *
13995 * Return: 0 for success, non-zero for failure
13996 */
13997static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13998{
13999 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14000
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053014001#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014002#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053014003#endif
14004#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014005#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053014006#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014007 /*set key mgmt type */
14008 switch (key_mgmt) {
14009 case WLAN_AKM_SUITE_PSK:
14010 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014011 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014012 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014013 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
14014 break;
14015
14016 case WLAN_AKM_SUITE_8021X_SHA256:
14017 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014018 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014019 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014020 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
14021 break;
14022#ifdef FEATURE_WLAN_ESE
14023#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
14024#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
14025 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014026 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014027 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
14028 break;
14029#endif
14030#ifndef WLAN_AKM_SUITE_OSEN
14031#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
14032#endif
14033 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014034 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014035 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
14036 break;
14037
14038 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014039 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014040 return -EINVAL;
14041
14042 }
14043 return 0;
14044}
14045
14046/**
14047 * wlan_hdd_cfg80211_set_cipher() - set encryption type
14048 * @pAdapter: Pointer to adapter
14049 * @cipher: Cipher type
14050 * @ucast: Unicast flag
14051 *
14052 * This function is used to set the encryption type
14053 * (NONE/WEP40/WEP104/TKIP/CCMP).
14054 *
14055 * Return: 0 for success, non-zero for failure
14056 */
14057static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
14058 u32 cipher, bool ucast)
14059{
14060 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14061 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14062 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14063
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014064 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014065 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014066 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14067 } else {
14068
14069 /*set encryption method */
14070 switch (cipher) {
14071 case IW_AUTH_CIPHER_NONE:
14072 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14073 break;
14074
14075 case WLAN_CIPHER_SUITE_WEP40:
14076 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
14077 break;
14078
14079 case WLAN_CIPHER_SUITE_WEP104:
14080 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
14081 break;
14082
14083 case WLAN_CIPHER_SUITE_TKIP:
14084 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
14085 break;
14086
14087 case WLAN_CIPHER_SUITE_CCMP:
14088 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14089 break;
14090#ifdef FEATURE_WLAN_WAPI
14091 case WLAN_CIPHER_SUITE_SMS4:
14092 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
14093 break;
14094#endif
14095
14096#ifdef FEATURE_WLAN_ESE
14097 case WLAN_CIPHER_SUITE_KRK:
14098 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
14099 break;
14100#ifdef WLAN_FEATURE_ROAM_OFFLOAD
14101 case WLAN_CIPHER_SUITE_BTK:
14102 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
14103 break;
14104#endif
14105#endif
14106 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014107 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014108 return -EOPNOTSUPP;
14109 }
14110 }
14111
14112 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014113 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014114 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14115 pWextState->roamProfile.EncryptionType.numEntries = 1;
14116 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14117 encryptionType;
14118 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014119 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014120 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
14121 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
14122 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
14123 encryptionType;
14124 }
14125
14126 return 0;
14127}
14128
14129/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014130 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
14131 * @wext_state: Pointer to wext state
14132 * @gen_ie: Pointer to IE data
14133 * @len: length of IE data
14134 *
14135 * Return: 0 for success, non-zero for failure
14136 */
14137static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
14138 const uint8_t *gen_ie, uint16_t len)
14139{
14140 uint16_t cur_add_ie_len =
14141 wext_state->assocAddIE.length;
14142
14143 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14144 (wext_state->assocAddIE.length + len)) {
14145 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
14146 QDF_ASSERT(0);
14147 return -ENOMEM;
14148 }
14149 memcpy(wext_state->assocAddIE.addIEdata +
14150 cur_add_ie_len, gen_ie, len);
14151 wext_state->assocAddIE.length += len;
14152
14153 wext_state->roamProfile.pAddIEAssoc =
14154 wext_state->assocAddIE.addIEdata;
14155 wext_state->roamProfile.nAddIEAssocLength =
14156 wext_state->assocAddIE.length;
14157 return 0;
14158}
14159
14160/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161 * wlan_hdd_cfg80211_set_ie() - set IEs
14162 * @pAdapter: Pointer to adapter
14163 * @ie: Pointer ot ie
14164 * @ie: IE length
14165 *
14166 * Return: 0 for success, non-zero for failure
14167 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014168static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014169 size_t ie_len)
14170{
14171 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14172 const uint8_t *genie = ie;
14173 uint16_t remLen = ie_len;
14174#ifdef FEATURE_WLAN_WAPI
14175 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
14176 u16 *tmp;
14177 uint16_t akmsuiteCount;
14178 int *akmlist;
14179#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014180 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014181
14182 /* clear previous assocAddIE */
14183 pWextState->assocAddIE.length = 0;
14184 pWextState->roamProfile.bWPSAssociation = false;
14185 pWextState->roamProfile.bOSENAssociation = false;
14186
14187 while (remLen >= 2) {
14188 uint16_t eLen = 0;
14189 uint8_t elementId;
14190 elementId = *genie++;
14191 eLen = *genie++;
14192 remLen -= 2;
14193
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014194 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014195
14196 switch (elementId) {
14197 case DOT11F_EID_WPA:
14198 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 -070014199 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200 return -EINVAL;
14201 } else if (0 ==
14202 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
14203 uint16_t curAddIELen =
14204 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014205 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014206
14207 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14208 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014209 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014210 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014211 return -ENOMEM;
14212 }
14213 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
14214 memcpy(pWextState->assocAddIE.addIEdata +
14215 curAddIELen, genie - 2, eLen + 2);
14216 pWextState->assocAddIE.length += eLen + 2;
14217
14218 pWextState->roamProfile.bWPSAssociation = true;
14219 pWextState->roamProfile.pAddIEAssoc =
14220 pWextState->assocAddIE.addIEdata;
14221 pWextState->roamProfile.nAddIEAssocLength =
14222 pWextState->assocAddIE.length;
14223 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014224 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014225 memset(pWextState->WPARSNIE, 0,
14226 MAX_WPA_RSN_IE_LEN);
14227 memcpy(pWextState->WPARSNIE, genie - 2,
14228 (eLen + 2));
14229 pWextState->roamProfile.pWPAReqIE =
14230 pWextState->WPARSNIE;
14231 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
14232 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
14233 P2P_OUI_TYPE_SIZE))) {
14234 uint16_t curAddIELen =
14235 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014236 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014237
14238 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14239 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014240 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014241 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014242 return -ENOMEM;
14243 }
14244 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
14245 memcpy(pWextState->assocAddIE.addIEdata +
14246 curAddIELen, genie - 2, eLen + 2);
14247 pWextState->assocAddIE.length += eLen + 2;
14248
14249 pWextState->roamProfile.pAddIEAssoc =
14250 pWextState->assocAddIE.addIEdata;
14251 pWextState->roamProfile.nAddIEAssocLength =
14252 pWextState->assocAddIE.length;
14253 }
14254#ifdef WLAN_FEATURE_WFD
14255 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
14256 WFD_OUI_TYPE_SIZE)) &&
14257 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080014258 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259 pAdapter->device_mode)) {
14260 uint16_t curAddIELen =
14261 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014262 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014263
14264 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14265 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014266 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014267 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014268 return -ENOMEM;
14269 }
14270 /* WFD IE is saved to Additional IE ; it should
14271 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014272 * WFD IE
14273 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274 memcpy(pWextState->assocAddIE.addIEdata +
14275 curAddIELen, genie - 2, eLen + 2);
14276 pWextState->assocAddIE.length += eLen + 2;
14277
14278 pWextState->roamProfile.pAddIEAssoc =
14279 pWextState->assocAddIE.addIEdata;
14280 pWextState->roamProfile.nAddIEAssocLength =
14281 pWextState->assocAddIE.length;
14282 }
14283#endif
14284 /* Appending HS 2.0 Indication Element in Assiciation Request */
14285 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
14286 HS20_OUI_TYPE_SIZE))) {
14287 uint16_t curAddIELen =
14288 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014289 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014290
14291 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14292 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014293 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014294 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014295 return -ENOMEM;
14296 }
14297 memcpy(pWextState->assocAddIE.addIEdata +
14298 curAddIELen, genie - 2, eLen + 2);
14299 pWextState->assocAddIE.length += eLen + 2;
14300
14301 pWextState->roamProfile.pAddIEAssoc =
14302 pWextState->assocAddIE.addIEdata;
14303 pWextState->roamProfile.nAddIEAssocLength =
14304 pWextState->assocAddIE.length;
14305 }
14306 /* Appending OSEN Information Element in Assiciation Request */
14307 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
14308 OSEN_OUI_TYPE_SIZE))) {
14309 uint16_t curAddIELen =
14310 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014311 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014312
14313 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14314 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014315 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014316 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014317 return -ENOMEM;
14318 }
14319 memcpy(pWextState->assocAddIE.addIEdata +
14320 curAddIELen, genie - 2, eLen + 2);
14321 pWextState->assocAddIE.length += eLen + 2;
14322
14323 pWextState->roamProfile.bOSENAssociation = true;
14324 pWextState->roamProfile.pAddIEAssoc =
14325 pWextState->assocAddIE.addIEdata;
14326 pWextState->roamProfile.nAddIEAssocLength =
14327 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014328 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
14329 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014330 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014331 status = wlan_hdd_add_assoc_ie(pWextState,
14332 genie - 2, eLen + 2);
14333 if (status)
14334 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014335 } else {
14336 uint16_t add_ie_len =
14337 pWextState->assocAddIE.length;
14338
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014339 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014340
14341 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14342 (pWextState->assocAddIE.length + eLen)) {
14343 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014344 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014345 return -ENOMEM;
14346 }
14347
14348 memcpy(pWextState->assocAddIE.addIEdata +
14349 add_ie_len, genie - 2, eLen + 2);
14350 pWextState->assocAddIE.length += eLen + 2;
14351
14352 pWextState->roamProfile.pAddIEAssoc =
14353 pWextState->assocAddIE.addIEdata;
14354 pWextState->roamProfile.nAddIEAssocLength =
14355 pWextState->assocAddIE.length;
14356 }
14357 break;
14358 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014359 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014360 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
14361 memcpy(pWextState->WPARSNIE, genie - 2,
14362 (eLen + 2));
14363 pWextState->roamProfile.pRSNReqIE =
14364 pWextState->WPARSNIE;
14365 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
14366 break;
14367 /*
14368 * Appending Extended Capabilities with Interworking bit set
14369 * in Assoc Req.
14370 *
14371 * In assoc req this EXT Cap will only be taken into account if
14372 * interworkingService bit is set to 1. Currently
14373 * driver is only interested in interworkingService capability
14374 * from supplicant. If in future any other EXT Cap info is
14375 * required from supplicat, it needs to be handled while
14376 * sending Assoc Req in LIM.
14377 */
14378 case DOT11F_EID_EXTCAP:
14379 {
14380 uint16_t curAddIELen =
14381 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014382 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014383
14384 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14385 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014386 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014387 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014388 return -ENOMEM;
14389 }
14390 memcpy(pWextState->assocAddIE.addIEdata +
14391 curAddIELen, genie - 2, eLen + 2);
14392 pWextState->assocAddIE.length += eLen + 2;
14393
14394 pWextState->roamProfile.pAddIEAssoc =
14395 pWextState->assocAddIE.addIEdata;
14396 pWextState->roamProfile.nAddIEAssocLength =
14397 pWextState->assocAddIE.length;
14398 break;
14399 }
14400#ifdef FEATURE_WLAN_WAPI
14401 case WLAN_EID_WAPI:
14402 /* Setting WAPI Mode to ON=1 */
14403 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014404 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014405 tmp = (u16 *) ie;
14406 tmp = tmp + 2; /* Skip element Id and Len, Version */
14407 akmsuiteCount = WPA_GET_LE16(tmp);
14408 tmp = tmp + 1;
14409 akmlist = (int *)(tmp);
14410 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
14411 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
14412 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014413 hdd_err("Invalid akmSuite count: %u",
14414 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014415 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014416 return -EINVAL;
14417 }
14418
14419 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014420 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014421 pAdapter->wapi_info.wapiAuthMode =
14422 WAPI_AUTH_MODE_PSK;
14423 }
14424 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014425 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014426 pAdapter->wapi_info.wapiAuthMode =
14427 WAPI_AUTH_MODE_CERT;
14428 }
14429 break;
14430#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014431 case DOT11F_EID_SUPPOPERATINGCLASSES:
14432 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014433 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014434 status = wlan_hdd_add_assoc_ie(pWextState,
14435 genie - 2, eLen + 2);
14436 if (status)
14437 return status;
14438 break;
14439 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014440 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014441 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014442 /* when Unknown IE is received we break
14443 * and continue to the next IE in the buffer
14444 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014445 break;
14446 }
14447 genie += eLen;
14448 remLen -= eLen;
14449 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450 return 0;
14451}
14452
14453/**
14454 * hdd_is_wpaie_present() - check for WPA ie
14455 * @ie: Pointer to ie
14456 * @ie_len: Ie length
14457 *
14458 * Parse the received IE to find the WPA IE
14459 *
14460 * Return: true if wpa ie is found else false
14461 */
14462static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
14463{
14464 uint8_t eLen = 0;
14465 uint16_t remLen = ie_len;
14466 uint8_t elementId = 0;
14467
14468 while (remLen >= 2) {
14469 elementId = *ie++;
14470 eLen = *ie++;
14471 remLen -= 2;
14472 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014473 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014474 return false;
14475 }
14476 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
14477 /* OUI - 0x00 0X50 0XF2
14478 * WPA Information Element - 0x01
14479 * WPA version - 0x01
14480 */
14481 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
14482 return true;
14483 }
14484 ie += eLen;
14485 remLen -= eLen;
14486 }
14487 return false;
14488}
14489
14490/**
14491 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
14492 * @pAdapter: Pointer to adapter
14493 * @req: Pointer to security parameters
14494 *
14495 * Return: 0 for success, non-zero for failure
14496 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014497static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
14498 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014499{
14500 int status = 0;
14501 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14502 ENTER();
14503
14504 /*set wpa version */
14505 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
14506
14507 if (req->crypto.wpa_versions) {
14508 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
14509 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
14510 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
14511 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14512 }
14513 }
14514
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014515 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014516
14517 /*set authentication type */
14518 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
14519
14520 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014521 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014522 return status;
14523 }
14524
14525 /*set key mgmt type */
14526 if (req->crypto.n_akm_suites) {
14527 status =
14528 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
14529 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014530 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014531 return status;
14532 }
14533 }
14534
14535 /*set pairwise cipher type */
14536 if (req->crypto.n_ciphers_pairwise) {
14537 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
14538 req->crypto.
14539 ciphers_pairwise[0],
14540 true);
14541 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014542 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014543 return status;
14544 }
14545 } else {
14546 /*Reset previous cipher suite to none */
14547 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14548 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014549 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014550 return status;
14551 }
14552 }
14553
14554 /*set group cipher type */
14555 status =
14556 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14557 false);
14558
14559 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014560 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561 return status;
14562 }
14563#ifdef WLAN_FEATURE_11W
14564 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14565#endif
14566
14567 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14568 if (req->ie_len) {
14569 status =
14570 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14571 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014572 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014573 return status;
14574 }
14575 }
14576
14577 /*incase of WEP set default key information */
14578 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014579 u8 key_len = req->key_len;
14580 u8 key_idx = req->key_idx;
14581
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014582 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14583 || (WLAN_CIPHER_SUITE_WEP104 ==
14584 req->crypto.ciphers_pairwise[0])
14585 ) {
14586 if (IW_AUTH_KEY_MGMT_802_1X
14587 ==
14588 (pWextState->
14589 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014590 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014591 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014592 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014593
Jeff Johnson68755312017-02-10 11:46:55 -080014594 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14595 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014596 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014597 key_idx, key_len);
14598 qdf_mem_copy(&pWextState->roamProfile.
14599 Keys.
14600 KeyMaterial[key_idx][0],
14601 req->key, key_len);
14602 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014603 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014604 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014605 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014606 }
14607 }
14608 }
14609
14610 return status;
14611}
14612
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014613int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014614{
14615 unsigned long rc;
14616 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014617 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014618 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014619
14620 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014621 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14622 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014623 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014624 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14625 }
14626 /*
14627 * If firmware has already started roaming process, driver
14628 * needs to defer the processing of this disconnect request.
14629 *
14630 */
14631 if (hdd_is_roaming_in_progress(pAdapter)) {
14632 /*
14633 * Defer the disconnect action until firmware roaming
14634 * result is received. If STA is in connected state after
14635 * that, send the disconnect command to CSR, otherwise
14636 * CSR would have already sent disconnect event to upper
14637 * layer.
14638 */
14639
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014640 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014641 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14642 pAdapter->cfg80211_disconnect_reason =
14643 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14644 return 0;
14645 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014646
Jeff Johnson9edf9572016-10-03 15:24:49 -070014647 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014648 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14649 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14650 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014651 hdd_conn_set_connection_state(pAdapter,
14652 eConnectionState_Disconnecting);
14653 /* Issue disconnect to CSR */
14654 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014655
14656 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14657 pAdapter->sessionId,
14658 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14659 /*
14660 * Wait here instead of returning directly, this will block the
14661 * next connect command and allow processing of the scan for
14662 * ssid and the previous connect command in CSR. Else we might
14663 * hit some race conditions leading to SME and HDD out of sync.
14664 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014665 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014666 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014667 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014668 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014669 (int)status);
14670 pHddStaCtx->staDebugState = status;
14671 result = -EINVAL;
14672 goto disconnected;
14673 }
14674
14675 rc = wait_for_completion_timeout(
14676 &pAdapter->disconnect_comp_var,
14677 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014678 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014679 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014680 pAdapter->sessionId, pHddStaCtx->staDebugState);
14681 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014682 }
14683 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014684 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014685 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014686 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014687 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014688 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014689 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014690 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014691 }
14692 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014693disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014694 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14695 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014696}
14697
14698/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014699 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14700 * @adapter: Pointer to the HDD adapter
14701 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014702 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014703 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014704 * This function will start reassociation if prev_bssid is set and bssid/
14705 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014706 *
Naveen Rawat07332902016-07-27 09:13:17 -070014707 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014708 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014709#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14710 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014711static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14712 struct cfg80211_connect_params *req,
14713 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014714{
Naveen Rawat07332902016-07-27 09:13:17 -070014715 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014716 const uint8_t *bssid = NULL;
14717 uint16_t channel = 0;
Arif Hussain43354e62017-05-24 11:24:25 -070014718 hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014719
14720 if (req->bssid)
14721 bssid = req->bssid;
14722 else if (req->bssid_hint)
14723 bssid = req->bssid_hint;
14724
14725 if (req->channel)
14726 channel = req->channel->hw_value;
14727 else if (req->channel_hint)
14728 channel = req->channel_hint->hw_value;
14729
14730 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014731 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014732 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014733 channel, MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070014734 /*
14735 * Save BSSID in a separate variable as
14736 * pRoamProfile's BSSID is getting zeroed out in the
14737 * association process. In case of join failure
14738 * we should send valid BSSID to supplicant
14739 */
14740 qdf_mem_copy(wext_state->req_bssId.bytes, bssid,
14741 QDF_MAC_ADDR_SIZE);
14742
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014743 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014744 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014745 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014746 }
Naveen Rawat07332902016-07-27 09:13:17 -070014747 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014748}
14749#else
Naveen Rawat07332902016-07-27 09:13:17 -070014750static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14751 struct cfg80211_connect_params *req,
14752 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014753{
Naveen Rawat07332902016-07-27 09:13:17 -070014754 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014755}
14756#endif
14757
14758/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014759 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14760 * @wiphy: Pointer to wiphy
14761 * @dev: Pointer to network device
14762 * @req: Pointer to cfg80211 connect request
14763 *
14764 * This function is used to start the association process
14765 *
14766 * Return: 0 for success, non-zero for failure
14767 */
14768static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14769 struct net_device *ndev,
14770 struct cfg80211_connect_params *req)
14771{
14772 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014773 u16 channel;
14774#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14775 const u8 *bssid_hint = req->bssid_hint;
14776#else
14777 const u8 *bssid_hint = NULL;
14778#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014779 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14780 hdd_context_t *pHddCtx;
14781
14782 ENTER();
14783
Anurag Chouhan6d760662016-02-20 16:05:43 +053014784 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014785 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014786 return -EINVAL;
14787 }
14788
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014789 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14790 hdd_err("invalid session id: %d", pAdapter->sessionId);
14791 return -EINVAL;
14792 }
14793
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014794 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014795 TRACE_CODE_HDD_CFG80211_CONNECT,
14796 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014797 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014798 hdd_device_mode_to_string(pAdapter->device_mode),
14799 pAdapter->device_mode);
14800
Krunal Sonib4326f22016-03-10 13:05:51 -080014801 if (pAdapter->device_mode != QDF_STA_MODE &&
14802 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014803 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804 hdd_device_mode_to_string(pAdapter->device_mode),
14805 pAdapter->device_mode);
14806 return -EINVAL;
14807 }
14808
14809 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14810 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014811 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014812 return -EINVAL;
14813 }
14814
14815 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014816 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014817 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014818
Naveen Rawat07332902016-07-27 09:13:17 -070014819 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014820 return status;
14821
Agrawal Ashishf156e942016-08-04 14:54:47 +053014822 /* Try disconnecting if already in connected state */
14823 status = wlan_hdd_try_disconnect(pAdapter);
14824 if (0 > status) {
14825 hdd_err("Failed to disconnect the existing connection");
14826 return -EALREADY;
14827 }
14828
14829 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014831 bool ok;
14832
14833 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14834 pHddCtx->hdd_psoc,
14835 req->channel->hw_value,
14836 &ok)) {
14837 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14838 req->channel->hw_value);
14839 return -EINVAL;
14840 }
14841 /**
14842 * Send connection timedout, so that Android framework does not
14843 * blacklist us.
14844 */
14845 if (!ok) {
14846 struct ieee80211_channel *chan =
14847 __ieee80211_get_channel(wiphy,
14848 wlan_chan_to_freq(req->channel->hw_value));
14849 struct cfg80211_bss *bss;
14850
14851 hdd_warn("Channel:%d not OK for DNBS",
14852 req->channel->hw_value);
14853 if (chan) {
14854 bss = hdd_cfg80211_get_bss(wiphy,
14855 chan,
14856 req->bssid, req->ssid,
14857 req->ssid_len);
14858 if (bss) {
14859 cfg80211_assoc_timeout(ndev, bss);
14860 return -ETIMEDOUT;
14861 }
14862 }
14863 return -EINVAL;
14864 }
14865
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014866 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14867 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014868 pAdapter->device_mode),
14869 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014870 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014871 return -ECONNREFUSED;
14872 }
14873 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014874 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14875 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014876 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014877 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014878 return -ECONNREFUSED;
14879 }
14880 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014881
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014882 /*initialise security parameters */
14883 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14884
14885 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014886 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014887 return status;
14888 }
14889
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014890 if (req->channel)
14891 channel = req->channel->hw_value;
14892 else
14893 channel = 0;
14894 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14895 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014896 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014897 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014898 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014899 return status;
14900 }
14901 EXIT();
14902 return status;
14903}
14904
14905/**
14906 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14907 * @wiphy: Pointer to wiphy
14908 * @dev: Pointer to network device
14909 * @req: Pointer to cfg80211 connect request
14910 *
14911 * Return: 0 for success, non-zero for failure
14912 */
14913static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14914 struct net_device *ndev,
14915 struct cfg80211_connect_params *req)
14916{
14917 int ret;
14918 cds_ssr_protect(__func__);
14919 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14920 cds_ssr_unprotect(__func__);
14921
14922 return ret;
14923}
14924
14925/**
14926 * wlan_hdd_disconnect() - hdd disconnect api
14927 * @pAdapter: Pointer to adapter
14928 * @reason: Disconnect reason code
14929 *
14930 * This function is used to issue a disconnect request to SME
14931 *
14932 * Return: 0 for success, non-zero for failure
14933 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014934static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014935{
14936 int status, result = 0;
14937 unsigned long rc;
14938 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14939 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014940 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014941 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014942
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014943 ENTER();
14944
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014945 status = wlan_hdd_validate_context(pHddCtx);
14946
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014947 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014948 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014949 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014950 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014951 status = sme_stop_roaming(hal, pAdapter->sessionId,
14952 eCsrHddIssued);
14953 }
14954 /*
14955 * If firmware has already started roaming process, driver
14956 * needs to defer the processing of this disconnect request.
14957 */
14958 if (hdd_is_roaming_in_progress(pAdapter)) {
14959 /*
14960 * Defer the disconnect action until firmware roaming
14961 * result is received. If STA is in connected state after
14962 * that, send the disconnect command to CSR, otherwise
14963 * CSR would have already sent disconnect event to upper
14964 * layer.
14965 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014966 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014967 pAdapter->defer_disconnect =
14968 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14969 pAdapter->cfg80211_disconnect_reason = reason;
14970 return 0;
14971 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014972
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014973 prev_conn_state = pHddStaCtx->conn_info.connState;
14974
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014975 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014976 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014977 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014978 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014979 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014980 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14981 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14982
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014983 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014984
14985 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14986 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014987 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14988 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014989 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014990 result = 0;
14991 goto disconnected;
14992 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14993 /*
14994 * Wait here instead of returning directly, this will block the
14995 * next connect command and allow processing of the scan for
14996 * ssid and the previous connect command in CSR. Else we might
14997 * hit some race conditions leading to SME and HDD out of sync.
14998 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014999 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015000 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015001 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015002 pHddStaCtx->staDebugState = status;
15003 result = -EINVAL;
15004 goto disconnected;
15005 }
15006 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15007 msecs_to_jiffies
15008 (WLAN_WAIT_TIME_DISCONNECT));
15009
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015010 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015011 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015012 result = -ETIMEDOUT;
15013 }
15014disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015015 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
15016#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
15017 /* Sending disconnect event to userspace for kernel version < 3.11
15018 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
15019 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015020 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053015021 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
15022 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015023#endif
15024
15025 return result;
15026}
15027
15028/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080015029 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
15030 * @reason: ieee80211 reason code.
15031 *
15032 * This utility function helps log string conversion of reason code.
15033 *
15034 * Return: string conversion of reason code, if match found;
15035 * "Unknown" otherwise.
15036 */
15037static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
15038{
15039 switch (reason) {
15040 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
15041 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
15042 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
15043 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
15044 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
15045 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
15046 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
15047 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
15048 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
15049 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
15050 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
15051 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
15052 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
15053 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
15054 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
15055 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
15056 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
15057 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
15058 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
15059 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
15060 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
15061 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
15062 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
15063 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
15064 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
15065 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
15066 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
15067 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
15068 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
15069 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
15070 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
15071 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
15072 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
15073 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
15074 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
15075 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
15076 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
15077 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
15078 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
15079 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
15080 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
15081 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
15082 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
15083 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
15084 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
15085 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
15086 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
15087 default:
15088 return "Unknown";
15089 }
15090}
15091
15092/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015093 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
15094 * @wiphy: Pointer to wiphy
15095 * @dev: Pointer to network device
15096 * @reason: Disconnect reason code
15097 *
15098 * This function is used to issue a disconnect request to SME
15099 *
15100 * Return: 0 for success, non-zero for failure
15101 */
15102static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
15103 struct net_device *dev, u16 reason)
15104{
15105 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15106 int status;
15107 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15108 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15109#ifdef FEATURE_WLAN_TDLS
15110 uint8_t staIdx;
15111#endif
15112
15113 ENTER();
15114
Anurag Chouhan6d760662016-02-20 16:05:43 +053015115 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015116 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015117 return -EINVAL;
15118 }
15119
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015120 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015121 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015122 return -EINVAL;
15123 }
15124
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015125 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015126 TRACE_CODE_HDD_CFG80211_DISCONNECT,
15127 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015128 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015129 hdd_device_mode_to_string(pAdapter->device_mode),
15130 pAdapter->device_mode, reason);
15131
15132 status = wlan_hdd_validate_context(pHddCtx);
15133
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015134 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015135 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015136
15137 /* Issue disconnect request to SME, if station is in connected state */
15138 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
15139 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
15140 eCsrRoamDisconnectReason reasonCode =
15141 eCSR_DISCONNECT_REASON_UNSPECIFIED;
15142 hdd_scaninfo_t *pScanInfo;
15143
15144 switch (reason) {
15145 case WLAN_REASON_MIC_FAILURE:
15146 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
15147 break;
15148
15149 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
15150 case WLAN_REASON_DISASSOC_AP_BUSY:
15151 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
15152 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
15153 break;
15154
15155 case WLAN_REASON_PREV_AUTH_NOT_VALID:
15156 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
15157 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
15158 break;
15159
15160 case WLAN_REASON_DEAUTH_LEAVING:
15161 reasonCode =
15162 pHddCtx->config->
15163 gEnableDeauthToDisassocMap ?
15164 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
15165 eCSR_DISCONNECT_REASON_DEAUTH;
15166 break;
15167 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
15168 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
15169 break;
15170 default:
15171 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
15172 break;
15173 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015174 pScanInfo = &pAdapter->scan_info;
15175 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015176 hdd_debug("Disconnect is in progress, Aborting Scan");
Abhishek Singh69ccb512017-04-25 11:58:16 +053015177 wlan_abort_scan(pHddCtx->hdd_pdev, INVAL_PDEV_ID,
15178 pAdapter->sessionId, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015179 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053015180 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015181#ifdef FEATURE_WLAN_TDLS
15182 /* First clean up the tdls peers if any */
15183 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
15184 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
15185 pAdapter->sessionId)
15186 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
15187 uint8_t *mac;
15188 mac =
15189 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015190 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015191 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015192 pHddCtx->tdlsConnInfo[staIdx].staId,
15193 pAdapter->sessionId,
15194 MAC_ADDR_ARRAY(mac));
15195 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
15196 (pAdapter),
15197 pAdapter->sessionId, mac);
15198 }
15199 }
Kabilan Kannanaad2f032017-05-08 13:25:37 -070015200 hdd_notify_sta_disconnect(pAdapter->sessionId,
15201 true, pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015202#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070015203 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
15204 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015205 status = wlan_hdd_disconnect(pAdapter, reasonCode);
15206 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015207 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015208 return -EINVAL;
15209 }
15210 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015211 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015212 pHddStaCtx->conn_info.connState);
15213 }
15214
15215 return status;
15216}
15217
15218/**
15219 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
15220 * @wiphy: Pointer to wiphy
15221 * @dev: Pointer to network device
15222 * @reason: Disconnect reason code
15223 *
15224 * Return: 0 for success, non-zero for failure
15225 */
15226static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
15227 struct net_device *dev, u16 reason)
15228{
15229 int ret;
15230 cds_ssr_protect(__func__);
15231 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
15232 cds_ssr_unprotect(__func__);
15233
15234 return ret;
15235}
15236
15237/**
15238 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
15239 * @pAdapter: Pointer to adapter
15240 * @param: Pointer to IBSS parameters
15241 *
15242 * This function is used to initialize the security settings in IBSS mode
15243 *
15244 * Return: 0 for success, non-zero for failure
15245 */
15246static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
15247 struct cfg80211_ibss_params
15248 *params)
15249{
15250 int status = 0;
15251 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15252 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
15253 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15254
15255 ENTER();
15256
15257 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015258 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015259 pHddStaCtx->ibss_enc_key_installed = 0;
15260
15261 if (params->ie_len && (NULL != params->ie)) {
15262 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
15263 params->ie_len, WLAN_EID_RSN)) {
15264 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
15265 encryptionType = eCSR_ENCRYPT_TYPE_AES;
15266 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
15267 tDot11fIEWPA dot11WPAIE;
15268 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15269 u8 *ie;
15270
15271 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
15272 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
15273 params->ie_len,
15274 DOT11F_EID_WPA);
15275 if (NULL != ie) {
15276 pWextState->wpaVersion =
15277 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015278 /* Unpack the WPA IE
15279 * Skip past the EID byte and length byte
15280 * and four byte WiFi OUI
15281 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015282 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053015283 &ie[2 + 4], ie[1] - 4,
15284 &dot11WPAIE, false);
15285 /*
15286 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015287 * encType for unicast cipher for
15288 * wpa-none is none
15289 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015290 encryptionType =
15291 hdd_translate_wpa_to_csr_encryption_type
15292 (dot11WPAIE.multicast_cipher);
15293 }
15294 }
15295
15296 status =
15297 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
15298 params->ie_len);
15299
15300 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015301 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015302 return status;
15303 }
15304 }
15305
15306 pWextState->roamProfile.AuthType.authType[0] =
15307 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
15308
15309 if (params->privacy) {
15310 /* Security enabled IBSS, At this time there is no information
15311 * available about the security paramters, so initialise the
15312 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
15313 * The correct security parameters will be updated later in
15314 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
15315 * set inorder enable privacy bit in beacons
15316 */
15317
15318 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
15319 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015320 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015321 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
15322 pWextState->roamProfile.EncryptionType.numEntries = 1;
15323 pWextState->roamProfile.EncryptionType.encryptionType[0] =
15324 encryptionType;
15325 return status;
15326}
15327
15328/**
15329 * __wlan_hdd_cfg80211_join_ibss() - join ibss
15330 * @wiphy: Pointer to wiphy
15331 * @dev: Pointer to network device
15332 * @param: Pointer to IBSS join parameters
15333 *
15334 * This function is used to create/join an IBSS network
15335 *
15336 * Return: 0 for success, non-zero for failure
15337 */
15338static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15339 struct net_device *dev,
15340 struct cfg80211_ibss_params *params)
15341{
15342 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15343 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15344 tCsrRoamProfile *pRoamProfile;
15345 int status;
15346 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15347 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053015348 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015349 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015350
15351 ENTER();
15352
Anurag Chouhan6d760662016-02-20 16:05:43 +053015353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015354 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015355 return -EINVAL;
15356 }
15357
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015358 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015359 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015360 return -EINVAL;
15361 }
15362
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015363 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015364 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
15365 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015366 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015367 hdd_device_mode_to_string(pAdapter->device_mode),
15368 pAdapter->device_mode);
15369
15370 status = wlan_hdd_validate_context(pHddCtx);
15371
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015372 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015373 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015374
15375 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053015376 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015377 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
15378 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
15379 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15380 int indx;
15381
15382 /* Get channel number */
15383 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015384 params->
15385 chandef.
15386 chan->
15387 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015388
15389 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
15390 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015391 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015392 return -EOPNOTSUPP;
15393 }
15394
15395 for (indx = 0; indx < numChans; indx++) {
15396 if (channelNum == validChan[indx]) {
15397 break;
15398 }
15399 }
15400 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015401 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015402 return -EINVAL;
15403 }
15404 }
15405
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015406 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
15407 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015408 hdd_err("This concurrency combination is not allowed");
15409 return -ECONNREFUSED;
15410 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015411
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015412 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015413 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015414 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015415
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015416 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
15417 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070015418 SIR_UPDATE_REASON_JOIN_IBSS);
15419 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015420 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070015421 return -EINVAL;
15422 }
15423
15424 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015425 status = policy_mgr_wait_for_connection_update(
15426 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015427 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015428 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015429 return -EINVAL;
15430 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015431 }
15432
15433 /*Try disconnecting if already in connected state */
15434 status = wlan_hdd_try_disconnect(pAdapter);
15435 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015436 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015437 return -EALREADY;
15438 }
15439
15440 pRoamProfile = &pWextState->roamProfile;
15441
15442 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015443 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015444 return -EINVAL;
15445 }
15446
15447 /* enable selected protection checks in IBSS mode */
15448 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
15449
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015450 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015451 WNI_CFG_IBSS_ATIM_WIN_SIZE,
15452 pHddCtx->config->
15453 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015454 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015455 }
15456
15457 /* BSSID is provided by upper layers hence no need to AUTO generate */
15458 if (NULL != params->bssid) {
15459 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015460 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015461 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015462 return -EIO;
15463 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015464 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015465 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
15466 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015467 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015468 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015469 return -EIO;
15470 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053015471 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015472 }
15473 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
15474 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
15475 pRoamProfile->beaconInterval = params->beacon_interval;
15476 else {
15477 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015478 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015479 params->beacon_interval, pRoamProfile->beaconInterval);
15480 }
15481
15482 /* Set Channel */
15483 if (channelNum) {
15484 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015485 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015486 pRoamProfile->ChannelInfo.numOfChannels = 1;
15487 pHddStaCtx->conn_info.operationChannel = channelNum;
15488 pRoamProfile->ChannelInfo.ChannelList =
15489 &pHddStaCtx->conn_info.operationChannel;
15490 }
15491
15492 /* Initialize security parameters */
15493 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
15494 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015495 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015496 return status;
15497 }
15498
15499 /* Issue connect start */
15500 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
15501 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015502 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015503 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015504 operationChannel,
15505 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015506
15507 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015508 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015509 return status;
15510 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015511 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015512 return 0;
15513}
15514
15515/**
15516 * wlan_hdd_cfg80211_join_ibss() - join ibss
15517 * @wiphy: Pointer to wiphy
15518 * @dev: Pointer to network device
15519 * @param: Pointer to IBSS join parameters
15520 *
15521 * This function is used to create/join an IBSS network
15522 *
15523 * Return: 0 for success, non-zero for failure
15524 */
15525static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15526 struct net_device *dev,
15527 struct cfg80211_ibss_params *params)
15528{
15529 int ret = 0;
15530
15531 cds_ssr_protect(__func__);
15532 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
15533 cds_ssr_unprotect(__func__);
15534
15535 return ret;
15536}
15537
15538/**
15539 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
15540 * @wiphy: Pointer to wiphy
15541 * @dev: Pointer to network device
15542 *
15543 * This function is used to leave an IBSS network
15544 *
15545 * Return: 0 for success, non-zero for failure
15546 */
15547static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15548 struct net_device *dev)
15549{
15550 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15551 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15552 tCsrRoamProfile *pRoamProfile;
15553 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15554 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015555 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015556 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015557 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015558
15559 ENTER();
15560
Anurag Chouhan6d760662016-02-20 16:05:43 +053015561 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015562 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015563 return -EINVAL;
15564 }
15565
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015566 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015567 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015568 return -EINVAL;
15569 }
15570
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015571 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015572 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15573 pAdapter->sessionId,
15574 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15575 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015576 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015578
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015579 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015580 hdd_device_mode_to_string(pAdapter->device_mode),
15581 pAdapter->device_mode);
15582 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015583 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015584 return -EIO;
15585 }
15586
15587 pRoamProfile = &pWextState->roamProfile;
15588
15589 /* Issue disconnect only if interface type is set to IBSS */
15590 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015591 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015592 return -EINVAL;
15593 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015594 /* Clearing add IE of beacon */
15595 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15596 sizeof(tSirMacAddr));
15597 updateIE.smeSessionId = pAdapter->sessionId;
15598 updateIE.ieBufferlength = 0;
15599 updateIE.pAdditionIEBuffer = NULL;
15600 updateIE.append = true;
15601 updateIE.notify = true;
15602 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15603 &updateIE,
15604 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015605 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015606 }
15607
15608 /* Reset WNI_CFG_PROBE_RSP Flags */
15609 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015610
15611 /* Issue Disconnect request */
15612 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15613 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15614 pAdapter->sessionId,
15615 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015616 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015617 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015618 hal_status);
15619 return -EAGAIN;
15620 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015621
15622 /* wait for mc thread to cleanup and then return to upper stack
15623 * so by the time upper layer calls the change interface, we are
15624 * all set to proceed further
15625 */
15626 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15627 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15628 if (!rc) {
15629 hdd_err("Failed to disconnect, timed out");
15630 return -ETIMEDOUT;
15631 }
15632
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015633 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015634 return 0;
15635}
15636
15637/**
15638 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15639 * @wiphy: Pointer to wiphy
15640 * @dev: Pointer to network device
15641 *
15642 * This function is used to leave an IBSS network
15643 *
15644 * Return: 0 for success, non-zero for failure
15645 */
15646static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15647 struct net_device *dev)
15648{
15649 int ret = 0;
15650
15651 cds_ssr_protect(__func__);
15652 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15653 cds_ssr_unprotect(__func__);
15654
15655 return ret;
15656}
15657
15658/**
15659 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15660 * @wiphy: Pointer to wiphy
15661 * @changed: Parameters changed
15662 *
15663 * This function is used to set the phy parameters. RTS Threshold/FRAG
15664 * Threshold/Retry Count etc.
15665 *
15666 * Return: 0 for success, non-zero for failure
15667 */
15668static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15669 u32 changed)
15670{
15671 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15672 tHalHandle hHal = pHddCtx->hHal;
15673 int status;
15674
15675 ENTER();
15676
Anurag Chouhan6d760662016-02-20 16:05:43 +053015677 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015678 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015679 return -EINVAL;
15680 }
15681
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015682 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015683 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15684 NO_SESSION, wiphy->rts_threshold));
15685 status = wlan_hdd_validate_context(pHddCtx);
15686
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015687 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015688 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015689
15690 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15691 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15692 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15693
15694 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15695 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015696 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015697 rts_threshold);
15698 return -EINVAL;
15699 }
15700
15701 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15702 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015703 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015704 rts_threshold);
15705 return -EIO;
15706 }
15707
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015708 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015709 }
15710
15711 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15712 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15713 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15714 wiphy->frag_threshold;
15715
15716 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15717 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015718 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015719 frag_threshold);
15720 return -EINVAL;
15721 }
15722
15723 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15724 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015725 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015726 frag_threshold);
15727 return -EIO;
15728 }
15729
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015730 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015731 }
15732
15733 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15734 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15735 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15736 wiphy->retry_short : wiphy->retry_long;
15737
15738 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15739 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015740 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015741 return -EINVAL;
15742 }
15743
15744 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15745 if (0 != sme_cfg_set_int(hHal,
15746 WNI_CFG_LONG_RETRY_LIMIT,
15747 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015748 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015749 retry_value);
15750 return -EIO;
15751 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015752 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015753 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15754 if (0 != sme_cfg_set_int(hHal,
15755 WNI_CFG_SHORT_RETRY_LIMIT,
15756 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015757 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015758 retry_value);
15759 return -EIO;
15760 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015761 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015762 }
15763 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015764 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015765 return 0;
15766}
15767
15768/**
15769 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15770 * @wiphy: Pointer to wiphy
15771 * @changed: Parameters changed
15772 *
15773 * Return: 0 for success, non-zero for failure
15774 */
15775static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15776{
15777 int ret;
15778
15779 cds_ssr_protect(__func__);
15780 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15781 cds_ssr_unprotect(__func__);
15782
15783 return ret;
15784}
15785
15786/**
15787 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15788 * key
15789 * @wiphy: Pointer to wiphy
15790 * @dev: Pointer to network device
15791 * @key_index: Key index
15792 *
15793 * Return: 0
15794 */
15795static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15796 struct net_device *netdev,
15797 u8 key_index)
15798{
15799 ENTER();
15800 return 0;
15801}
15802
15803/**
15804 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15805 * wlan_hdd_set_default_mgmt_key
15806 * @wiphy: pointer to wiphy
15807 * @netdev: pointer to net_device structure
15808 * @key_index: key index
15809 *
15810 * Return: 0 on success, error number on failure
15811 */
15812static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15813 struct net_device *netdev,
15814 u8 key_index)
15815{
15816 int ret;
15817
15818 cds_ssr_protect(__func__);
15819 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15820 cds_ssr_unprotect(__func__);
15821
15822 return ret;
15823}
15824
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015825/**
15826 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15827 * @wiphy: Pointer to wiphy
15828 * @dev: Pointer to network device
15829 * @params: Pointer to tx queue parameters
15830 *
15831 * Return: 0
15832 */
15833static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15834 struct net_device *dev,
15835 struct ieee80211_txq_params *params)
15836{
15837 ENTER();
15838 return 0;
15839}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015840
15841/**
15842 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15843 * @wiphy: pointer to wiphy
15844 * @netdev: pointer to net_device structure
15845 * @params: pointer to ieee80211_txq_params
15846 *
15847 * Return: 0 on success, error number on failure
15848 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015849static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15850 struct net_device *dev,
15851 struct ieee80211_txq_params *params)
15852{
15853 int ret;
15854
15855 cds_ssr_protect(__func__);
15856 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15857 cds_ssr_unprotect(__func__);
15858
15859 return ret;
15860}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015861
15862/**
15863 * __wlan_hdd_cfg80211_del_station() - delete station v2
15864 * @wiphy: Pointer to wiphy
15865 * @param: Pointer to delete station parameter
15866 *
15867 * Return: 0 for success, non-zero for failure
15868 */
15869static
15870int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15871 struct net_device *dev,
15872 struct tagCsrDelStaParams *pDelStaParams)
15873{
15874 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15875 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015876 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015877 hdd_hostapd_state_t *hapd_state;
15878 int status;
15879 uint8_t staId;
15880 uint8_t *mac;
15881
15882 ENTER();
15883
Anurag Chouhan6d760662016-02-20 16:05:43 +053015884 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015885 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015886 return -EINVAL;
15887 }
15888
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015889 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015890 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015891 return -EINVAL;
15892 }
15893
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015894 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015895 TRACE_CODE_HDD_CFG80211_DEL_STA,
15896 pAdapter->sessionId, pAdapter->device_mode));
15897
15898 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15899 status = wlan_hdd_validate_context(pHddCtx);
15900
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015901 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015902 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015903
15904 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15905
Krunal Sonib4326f22016-03-10 13:05:51 -080015906 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15907 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015908
15909 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15910 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015911 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015912 return 0;
15913 }
15914
Anurag Chouhanc5548422016-02-24 18:33:27 +053015915 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015916 uint16_t i;
15917 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15918 if ((pAdapter->aStaInfo[i].isUsed) &&
15919 (!pAdapter->aStaInfo[i].
15920 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015921 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015922 mac,
15923 pAdapter->aStaInfo[i].
15924 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015925 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015926 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15927 hdd_ipa_wlan_evt(pAdapter,
15928 pAdapter->
15929 aStaInfo[i].
15930 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015931 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015932 mac);
15933 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015934 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015935 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015936 MAC_ADDR_ARRAY(mac));
15937
15938 if (pHddCtx->dev_dfs_cac_status ==
15939 DFS_CAC_IN_PROGRESS)
15940 goto fn_end;
15941
Wei Song2f76f642016-11-18 16:32:53 +080015942 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015943 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015944 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015945 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015946 hdd_softap_sta_deauth(pAdapter,
15947 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015948 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015949 pAdapter->aStaInfo[i].
15950 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015951 qdf_status =
15952 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015953 &hapd_state->
15954 qdf_sta_disassoc_event,
15955 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015956 if (!QDF_IS_STATUS_SUCCESS(
15957 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015958 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015959 }
15960 }
15961 }
15962 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015963 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015964 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015965 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015966 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015967 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015968 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015969 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015970 MAC_ADDR_ARRAY(mac));
15971 return -ENOENT;
15972 }
15973
15974 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15975 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015976 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015977 }
15978
15979 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15980 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015981 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015982 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015983 MAC_ADDR_ARRAY(mac));
15984 return -ENOENT;
15985 }
15986
15987 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15988
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015989 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015990 MAC_ADDR_ARRAY(mac));
15991
15992 /* Case: SAP in ACS selected DFS ch and client connected
15993 * Now Radar detected. Then if random channel is another
15994 * DFS ch then new CAC is initiated and no TX allowed.
15995 * So do not send any mgmt frames as it will timeout
15996 * during CAC.
15997 */
15998
15999 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
16000 goto fn_end;
16001
Wei Song2f76f642016-11-18 16:32:53 +080016002 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053016003 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
16004 (pAdapter), pAdapter->sessionId,
16005 (uint8_t *)&pDelStaParams->peerMacAddr,
16006 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016007 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016008 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016009 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016010 pAdapter->aStaInfo[staId].isDeauthInProgress =
16011 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016012 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016013 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016014 MAC_ADDR_ARRAY(mac));
16015 return -ENOENT;
16016 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053016017 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080016018 &hapd_state->
16019 qdf_sta_disassoc_event,
16020 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053016021 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016022 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016023 }
16024 }
16025 }
16026
16027fn_end:
16028 EXIT();
16029 return 0;
16030}
16031
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080016032#if defined(USE_CFG80211_DEL_STA_V2)
16033/**
16034 * wlan_hdd_del_station() - delete station wrapper
16035 * @adapter: pointer to the hdd adapter
16036 *
16037 * Return: None
16038 */
16039void wlan_hdd_del_station(hdd_adapter_t *adapter)
16040{
16041 struct station_del_parameters del_sta;
16042 del_sta.mac = NULL;
16043 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
16044 del_sta.reason_code = eCsrForcedDeauthSta;
16045
16046 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
16047 &del_sta);
16048}
16049#else
16050void wlan_hdd_del_station(hdd_adapter_t *adapter)
16051{
16052 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
16053}
16054#endif
16055
16056#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016057/**
16058 * wlan_hdd_cfg80211_del_station() - delete station v2
16059 * @wiphy: Pointer to wiphy
16060 * @param: Pointer to delete station parameter
16061 *
16062 * Return: 0 for success, non-zero for failure
16063 */
16064int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
16065 struct net_device *dev,
16066 struct station_del_parameters *param)
16067#else
16068/**
16069 * wlan_hdd_cfg80211_del_station() - delete station
16070 * @wiphy: Pointer to wiphy
16071 * @mac: Pointer to station mac address
16072 *
16073 * Return: 0 for success, non-zero for failure
16074 */
16075#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
16076int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
16077 struct net_device *dev,
16078 const uint8_t *mac)
16079#else
16080int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
16081 struct net_device *dev,
16082 uint8_t *mac)
16083#endif
16084#endif
16085{
16086 int ret;
16087 struct tagCsrDelStaParams delStaParams;
16088
16089 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080016090#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016091 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080016092 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016093 return -EINVAL;
16094 }
16095 wlansap_populate_del_sta_params(param->mac, param->reason_code,
16096 param->subtype, &delStaParams);
16097#else
16098 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
16099 (SIR_MAC_MGMT_DEAUTH >> 4),
16100 &delStaParams);
16101#endif
16102 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
16103 cds_ssr_unprotect(__func__);
16104
16105 return ret;
16106}
16107
16108/**
16109 * __wlan_hdd_cfg80211_add_station() - add station
16110 * @wiphy: Pointer to wiphy
16111 * @mac: Pointer to station mac address
16112 * @pmksa: Pointer to add station parameter
16113 *
16114 * Return: 0 for success, non-zero for failure
16115 */
16116static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16117 struct net_device *dev,
16118 const uint8_t *mac,
16119 struct station_parameters *params)
16120{
16121 int status = -EPERM;
16122#ifdef FEATURE_WLAN_TDLS
16123 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16124 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16125 u32 mask, set;
16126
16127 ENTER();
16128
Anurag Chouhan6d760662016-02-20 16:05:43 +053016129 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016130 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016131 return -EINVAL;
16132 }
16133
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016134 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016135 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016136 return -EINVAL;
16137 }
16138
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016139 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016140 TRACE_CODE_HDD_CFG80211_ADD_STA,
16141 pAdapter->sessionId, params->listen_interval));
16142
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016143 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016144 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016145
16146 mask = params->sta_flags_mask;
16147
16148 set = params->sta_flags_set;
16149
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016150 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016151 MAC_ADDR_ARRAY(mac));
16152
16153 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
16154 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080016155#if defined(CONVERGED_TDLS_ENABLE)
16156 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
16157 dev, mac);
16158#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016159 status =
16160 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080016161#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016162 }
16163 }
16164#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016165 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016166 return status;
16167}
16168
16169/**
16170 * wlan_hdd_cfg80211_add_station() - add station
16171 * @wiphy: Pointer to wiphy
16172 * @mac: Pointer to station mac address
16173 * @pmksa: Pointer to add station parameter
16174 *
16175 * Return: 0 for success, non-zero for failure
16176 */
16177#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
16178static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16179 struct net_device *dev,
16180 const uint8_t *mac,
16181 struct station_parameters *params)
16182#else
16183static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16184 struct net_device *dev, uint8_t *mac,
16185 struct station_parameters *params)
16186#endif
16187{
16188 int ret;
16189
16190 cds_ssr_protect(__func__);
16191 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
16192 cds_ssr_unprotect(__func__);
16193
16194 return ret;
16195}
16196
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016197/**
16198 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
16199 * @wiphy: Pointer to wiphy
16200 * @dev: Pointer to network device
16201 * @pmksa: Pointer to set pmksa parameter
16202 *
16203 * Return: 0 for success, non-zero for failure
16204 */
16205static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
16206 struct net_device *dev,
16207 struct cfg80211_pmksa *pmksa)
16208{
16209 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16210 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16211 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016212 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016213 int status;
16214 tPmkidCacheInfo pmk_id;
16215
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016216 ENTER();
16217
Anurag Chouhan6d760662016-02-20 16:05:43 +053016218 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016219 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016220 return -EINVAL;
16221 }
16222
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016223 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016224 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016225 return -EINVAL;
16226 }
16227
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016228 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016229 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016230 return -EINVAL;
16231 }
16232
16233 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016234 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016235 pmksa->bssid, pmksa->pmkid);
16236 return -EINVAL;
16237 }
16238
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016239 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016240 MAC_ADDR_ARRAY(pmksa->bssid));
16241
16242 status = wlan_hdd_validate_context(pHddCtx);
16243
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016244 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016245 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016246
16247 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16248
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016249 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
16250 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016251
16252 /* Add to the PMKSA ID Cache in CSR */
16253 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
16254 &pmk_id, 1, false);
16255
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016256 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016257 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
16258 pAdapter->sessionId, result));
16259
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016260 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016261 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262}
16263
16264/**
16265 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
16266 * @wiphy: Pointer to wiphy
16267 * @dev: Pointer to network device
16268 * @pmksa: Pointer to set pmksa parameter
16269 *
16270 * Return: 0 for success, non-zero for failure
16271 */
16272static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
16273 struct net_device *dev,
16274 struct cfg80211_pmksa *pmksa)
16275{
16276 int ret;
16277
16278 cds_ssr_protect(__func__);
16279 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
16280 cds_ssr_unprotect(__func__);
16281
16282 return ret;
16283}
16284
16285/**
16286 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16287 * @wiphy: Pointer to wiphy
16288 * @dev: Pointer to network device
16289 * @pmksa: Pointer to pmksa parameter
16290 *
16291 * Return: 0 for success, non-zero for failure
16292 */
16293static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16294 struct net_device *dev,
16295 struct cfg80211_pmksa *pmksa)
16296{
16297 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16298 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16299 tHalHandle halHandle;
16300 int status = 0;
16301
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016302 ENTER();
16303
Anurag Chouhan6d760662016-02-20 16:05:43 +053016304 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016305 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016306 return -EINVAL;
16307 }
16308
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016309 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16310 hdd_err("invalid session id: %d", pAdapter->sessionId);
16311 return -EINVAL;
16312 }
16313
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016314 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016315 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016316 return -EINVAL;
16317 }
16318
16319 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016320 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016321 return -EINVAL;
16322 }
16323
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016324 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016325 MAC_ADDR_ARRAY(pmksa->bssid));
16326
16327 status = wlan_hdd_validate_context(pHddCtx);
16328
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016329 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016330 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016331
16332 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16333
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016334 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016335 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
16336 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016337 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016338 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016339 sme_roam_del_pmkid_from_cache(halHandle,
16340 pAdapter->sessionId, pmksa->bssid,
16341 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016342 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016343 MAC_ADDR_ARRAY(pmksa->bssid));
16344 status = -EINVAL;
16345 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016346 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016347 return status;
16348}
16349
16350/**
16351 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16352 * @wiphy: Pointer to wiphy
16353 * @dev: Pointer to network device
16354 * @pmksa: Pointer to pmksa parameter
16355 *
16356 * Return: 0 for success, non-zero for failure
16357 */
16358static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16359 struct net_device *dev,
16360 struct cfg80211_pmksa *pmksa)
16361{
16362 int ret;
16363
16364 cds_ssr_protect(__func__);
16365 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
16366 cds_ssr_unprotect(__func__);
16367
16368 return ret;
16369
16370}
16371
16372/**
16373 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16374 * @wiphy: Pointer to wiphy
16375 * @dev: Pointer to network device
16376 *
16377 * Return: 0 for success, non-zero for failure
16378 */
16379static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16380 struct net_device *dev)
16381{
16382 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16383 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16384 tHalHandle halHandle;
16385 int status = 0;
16386
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016387 ENTER();
16388
Anurag Chouhan6d760662016-02-20 16:05:43 +053016389 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016390 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016391 return -EINVAL;
16392 }
16393
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016394 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16395 hdd_err("invalid session id: %d", pAdapter->sessionId);
16396 return -EINVAL;
16397 }
16398
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016399 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016400
16401 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16402 status = wlan_hdd_validate_context(pHddCtx);
16403
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016404 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016405 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016406
16407 /* Retrieve halHandle */
16408 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16409
16410 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016411 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016412 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
16413 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016414 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016415 status = -EINVAL;
16416 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016417 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016418 return status;
16419}
16420
16421/**
16422 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16423 * @wiphy: Pointer to wiphy
16424 * @dev: Pointer to network device
16425 *
16426 * Return: 0 for success, non-zero for failure
16427 */
16428static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16429 struct net_device *dev)
16430{
16431 int ret;
16432
16433 cds_ssr_protect(__func__);
16434 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
16435 cds_ssr_unprotect(__func__);
16436
16437 return ret;
16438}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016439
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016440#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016441/**
16442 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16443 * @wiphy: Pointer to wiphy
16444 * @dev: Pointer to network device
16445 * @ftie: Pointer to fast transition ie parameter
16446 *
16447 * Return: 0 for success, non-zero for failure
16448 */
16449static int
16450__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16451 struct net_device *dev,
16452 struct cfg80211_update_ft_ies_params *ftie)
16453{
16454 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16455 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16456 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16457 int status;
16458
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016459 ENTER();
16460
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016461 status = wlan_hdd_validate_context(hdd_ctx);
16462 if (status)
16463 return status;
16464
Anurag Chouhan6d760662016-02-20 16:05:43 +053016465 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016466 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016467 return -EINVAL;
16468 }
16469
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016470 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16471 hdd_err("invalid session id: %d", pAdapter->sessionId);
16472 return -EINVAL;
16473 }
16474
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016475 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016476 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
16477 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
16478 /* Added for debug on reception of Re-assoc Req. */
16479 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016480 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016481 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016482 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016483 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016484 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016485 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016486
16487 /* Pass the received FT IEs to SME */
16488 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
16489 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016490 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016491 return 0;
16492}
16493
16494/**
16495 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16496 * @wiphy: Pointer to wiphy
16497 * @dev: Pointer to network device
16498 * @ftie: Pointer to fast transition ie parameter
16499 *
16500 * Return: 0 for success, non-zero for failure
16501 */
16502static int
16503wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16504 struct net_device *dev,
16505 struct cfg80211_update_ft_ies_params *ftie)
16506{
16507 int ret;
16508
16509 cds_ssr_protect(__func__);
16510 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
16511 cds_ssr_unprotect(__func__);
16512
16513 return ret;
16514}
16515#endif
16516
Mukul Sharma3d36c392017-01-18 18:39:12 +053016517void wlan_hdd_cfg80211_update_replay_counter_callback(
16518 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
16519
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016520{
Mukul Sharma3d36c392017-01-18 18:39:12 +053016521 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
16522 uint8_t temp_replay_counter[8];
16523 int i;
16524 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016525
16526 ENTER();
16527
Mukul Sharma3d36c392017-01-18 18:39:12 +053016528 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016529 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016530 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016531 }
16532
Mukul Sharma3d36c392017-01-18 18:39:12 +053016533 if (!gtk_rsp_param) {
16534 hdd_err("gtk_rsp_param is Null");
16535 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016536 }
16537
Mukul Sharma3d36c392017-01-18 18:39:12 +053016538 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016539 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016540 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016541 }
16542
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016543 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016544 gtk_rsp_param->replay_counter);
16545 /* convert little to big endian since supplicant works on big endian */
16546 p = (uint8_t *)&gtk_rsp_param->replay_counter;
16547 for (i = 0; i < 8; i++)
16548 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016549
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016550 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016551 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080016552 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016553 gtk_rsp_param->bssid.bytes,
16554 temp_replay_counter, GFP_KERNEL);
16555out:
16556 EXIT();
16557
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016558}
16559
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016560static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016561int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016562 struct net_device *dev,
16563 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016564{
16565 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016566 int result, i;
16567 struct pmo_gtk_req *gtk_req = NULL;
16568 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16569 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016570 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016571
16572 ENTER();
16573
Anurag Chouhan6d760662016-02-20 16:05:43 +053016574 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016575 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016576 result = -EINVAL;
16577 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016578 }
16579
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016580 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16581 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016582 result = -EINVAL;
16583 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016584 }
16585
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016586 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016587 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16588 pAdapter->sessionId, pAdapter->device_mode));
16589
Mukul Sharma3d36c392017-01-18 18:39:12 +053016590 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016591 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016592 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016593
Mukul Sharma3d36c392017-01-18 18:39:12 +053016594 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16595 if (!gtk_req) {
16596 hdd_err("cannot allocate gtk_req");
16597 result = -ENOMEM;
16598 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016599 }
16600
Mukul Sharma3d36c392017-01-18 18:39:12 +053016601 /* convert big to little endian since driver work on little endian */
16602 buf = (uint8_t *)&gtk_req->replay_counter;
16603 for (i = 0; i < 8; i++)
16604 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016605
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016606 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016607 gtk_req->replay_counter);
16608 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16609 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16610 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16611 if (status != QDF_STATUS_SUCCESS) {
16612 hdd_err("Failed to cache GTK Offload");
16613 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016614 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016615out:
16616 if (gtk_req)
16617 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016618 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016619
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016620 return result;
16621}
16622
16623/**
16624 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16625 * @wiphy: Pointer to wiphy
16626 * @dev: Pointer to network device
16627 * @data: Pointer to rekey data
16628 *
16629 * This function is used to offload GTK rekeying job to the firmware.
16630 *
16631 * Return: 0 for success, non-zero for failure
16632 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016633static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016634int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16635 struct net_device *dev,
16636 struct cfg80211_gtk_rekey_data *data)
16637{
16638 int ret;
16639
16640 cds_ssr_protect(__func__);
16641 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16642 cds_ssr_unprotect(__func__);
16643
16644 return ret;
16645}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016646
16647/**
16648 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16649 * @wiphy: Pointer to wiphy
16650 * @dev: Pointer to network device
16651 * @param: Pointer to access control parameter
16652 *
16653 * Return: 0 for success, non-zero for failure
16654 */
16655static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16656 struct net_device *dev,
16657 const struct cfg80211_acl_data *params)
16658{
16659 int i;
16660 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16661 hdd_hostapd_state_t *pHostapdState;
16662 tsap_Config_t *pConfig;
16663 v_CONTEXT_t p_cds_context = NULL;
16664 hdd_context_t *pHddCtx;
16665 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016666 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016667
16668 ENTER();
16669
Anurag Chouhan6d760662016-02-20 16:05:43 +053016670 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016671 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016672 return -EINVAL;
16673 }
16674
16675 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016676 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016677 return -EINVAL;
16678 }
16679
16680 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16681 status = wlan_hdd_validate_context(pHddCtx);
16682
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016683 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016684 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016685
16686 p_cds_context = pHddCtx->pcds_context;
16687 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16688
16689 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016690 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016691 return -EINVAL;
16692 }
16693
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016694 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016695 params->n_acl_entries);
16696
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016697 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016698 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16699 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016700 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016701 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16702
16703 /* default value */
16704 pConfig->num_accept_mac = 0;
16705 pConfig->num_deny_mac = 0;
16706
16707 /**
16708 * access control policy
16709 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16710 * listed in hostapd.deny file.
16711 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16712 * listed in hostapd.accept file.
16713 */
16714 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16715 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16716 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16717 params->acl_policy) {
16718 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16719 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016720 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016721 params->acl_policy);
16722 return -ENOTSUPP;
16723 }
16724
16725 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16726 pConfig->num_accept_mac = params->n_acl_entries;
16727 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016728 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016729 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016730 MAC_ADDR_ARRAY(
16731 params->mac_addrs[i].addr));
16732
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016733 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016734 params->mac_addrs[i].addr,
16735 sizeof(qcmacaddr));
16736 }
16737 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16738 pConfig->num_deny_mac = params->n_acl_entries;
16739 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016740 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016741 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016742 MAC_ADDR_ARRAY(
16743 params->mac_addrs[i].addr));
16744
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016745 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016746 params->mac_addrs[i].addr,
16747 sizeof(qcmacaddr));
16748 }
16749 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016750 qdf_status = wlansap_set_mac_acl(
16751 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016752 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016753 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016754 return -EINVAL;
16755 }
16756 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016757 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016758 hdd_device_mode_to_string(pAdapter->device_mode),
16759 pAdapter->device_mode);
16760 return -EINVAL;
16761 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016762 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016763 return 0;
16764}
16765
16766/**
16767 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16768 * __wlan_hdd_cfg80211_set_mac_acl
16769 * @wiphy: pointer to wiphy structure
16770 * @dev: pointer to net_device
16771 * @params: pointer to cfg80211_acl_data
16772 *
16773 * Return; 0 on success, error number otherwise
16774 */
16775static int
16776wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16777 struct net_device *dev,
16778 const struct cfg80211_acl_data *params)
16779{
16780 int ret;
16781
16782 cds_ssr_protect(__func__);
16783 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16784 cds_ssr_unprotect(__func__);
16785
16786 return ret;
16787}
16788
16789#ifdef WLAN_NL80211_TESTMODE
16790#ifdef FEATURE_WLAN_LPHB
16791/**
16792 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16793 * @pHddCtx: Pointer to hdd context
16794 * @lphbInd: Pointer to low power heart beat indication parameter
16795 *
16796 * Return: none
16797 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016798static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016799 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016800{
16801 struct sk_buff *skb;
16802
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016803 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016804
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016805 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016806 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016807
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016808 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016809 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016810 return;
16811 }
16812
16813 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016814 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016815 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016816 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016817 return;
16818 }
16819
16820 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016821 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016822 goto nla_put_failure;
16823 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016824 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016825 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016826 goto nla_put_failure;
16827 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016828 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16829 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016830 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016831 goto nla_put_failure;
16832 }
16833 cfg80211_testmode_event(skb, GFP_ATOMIC);
16834 return;
16835
16836nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016837 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016838 kfree_skb(skb);
16839
16840 return;
16841}
16842#endif /* FEATURE_WLAN_LPHB */
16843
16844/**
16845 * __wlan_hdd_cfg80211_testmode() - test mode
16846 * @wiphy: Pointer to wiphy
16847 * @data: Data pointer
16848 * @len: Data length
16849 *
16850 * Return: 0 for success, non-zero for failure
16851 */
16852static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16853 void *data, int len)
16854{
16855 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16856 int err;
16857 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16858
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016859 ENTER();
16860
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016861 err = wlan_hdd_validate_context(pHddCtx);
16862 if (err)
16863 return err;
16864
16865 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16866 len, wlan_hdd_tm_policy);
16867 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016868 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016869 return err;
16870 }
16871
16872 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016873 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016874 return -EINVAL;
16875 }
16876
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016877 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016878 TRACE_CODE_HDD_CFG80211_TESTMODE,
16879 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016880 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16881#ifdef FEATURE_WLAN_LPHB
16882 /* Low Power Heartbeat configuration request */
16883 case WLAN_HDD_TM_CMD_WLAN_HB:
16884 {
16885 int buf_len;
16886 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016887 struct pmo_lphb_req *hb_params = NULL;
16888 struct pmo_lphb_req *hb_params_temp = NULL;
16889 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016890
16891 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016892 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016893 return -EINVAL;
16894 }
16895
16896 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16897 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16898
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016899 hb_params_temp = (struct pmo_lphb_req *) buf;
16900 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16901 && (hb_params_temp->params.lphb_tcp_params.
16902 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016903 return -EINVAL;
16904
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016905 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16906 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016907 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016908 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016909 return -ENOMEM;
16910 }
16911
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016912 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016913 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16914 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016915 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016916 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016917 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016918
16919 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016920 return 0;
16921 }
16922#endif /* FEATURE_WLAN_LPHB */
16923
16924#if defined(QCA_WIFI_FTM)
16925 case WLAN_HDD_TM_CMD_WLAN_FTM:
16926 {
16927 int buf_len;
16928 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016929 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016930 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016931 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016932 return -EINVAL;
16933 }
16934
16935 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16936 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16937
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016938 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016939
16940 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16941
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016942 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016943 err = -EBUSY;
16944 break;
16945 }
16946#endif
16947
16948 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016949 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016950 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16951 return -EOPNOTSUPP;
16952 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016953 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016954 return err;
16955}
16956
16957/**
16958 * wlan_hdd_cfg80211_testmode() - test mode
16959 * @wiphy: Pointer to wiphy
16960 * @dev: Pointer to network device
16961 * @data: Data pointer
16962 * @len: Data length
16963 *
16964 * Return: 0 for success, non-zero for failure
16965 */
16966static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16967#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16968 struct wireless_dev *wdev,
16969#endif
16970 void *data, int len)
16971{
16972 int ret;
16973
16974 cds_ssr_protect(__func__);
16975 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16976 cds_ssr_unprotect(__func__);
16977
16978 return ret;
16979}
16980
16981#if defined(QCA_WIFI_FTM)
16982/**
16983 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16984 * @buf: Pointer to buffer
16985 * @buf_len: Buffer length
16986 *
16987 * Return: none
16988 */
16989void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16990{
16991 struct sk_buff *skb;
16992 hdd_context_t *hdd_ctx;
16993
16994 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016995 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016996 return;
16997 }
16998
Anurag Chouhan6d760662016-02-20 16:05:43 +053016999 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017000 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017001 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017002 return;
17003 }
17004
17005 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
17006 buf_len, GFP_KERNEL);
17007 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017008 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017009 return;
17010 }
17011
17012 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
17013 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
17014 goto nla_put_failure;
17015
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017016 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017017
17018 cfg80211_testmode_event(skb, GFP_KERNEL);
17019 return;
17020
17021nla_put_failure:
17022 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017023 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017024}
17025#endif
17026#endif /* CONFIG_NL80211_TESTMODE */
17027
17028#ifdef QCA_HT_2040_COEX
17029/**
17030 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
17031 * @wiphy: Pointer to wiphy
17032 * @dev: Pointer to network device
17033 * @chandef: Pointer to channel definition parameter
17034 *
17035 * Return: 0 for success, non-zero for failure
17036 */
17037static int
17038__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
17039 struct net_device *dev,
17040 struct cfg80211_chan_def *chandef)
17041{
17042 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
17043 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017044 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017045 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053017046 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017047
Anurag Chouhan6d760662016-02-20 16:05:43 +053017048 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017049 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017050 return -EINVAL;
17051 }
17052
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017053 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
17054 hdd_err("invalid session id: %d", pAdapter->sessionId);
17055 return -EINVAL;
17056 }
17057
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017058 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
17059 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053017060 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017061 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017062
Anurag Chouhan600c3a02016-03-01 10:33:54 +053017063 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017064 sme_get_config_param(pHddCtx->hHal, &sme_config);
17065 switch (chandef->width) {
17066 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053017067 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017068 if (sme_config.csrConfig.channelBondingMode24GHz !=
17069 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
17070 sme_config.csrConfig.channelBondingMode24GHz =
17071 eCSR_INI_SINGLE_CHANNEL_CENTERED;
17072 sme_update_config(pHddCtx->hHal, &sme_config);
17073 cbModeChange = true;
17074 }
17075 break;
17076
17077 case NL80211_CHAN_WIDTH_40:
17078 if (sme_config.csrConfig.channelBondingMode24GHz ==
17079 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
17080 if (NL80211_CHAN_HT40MINUS ==
17081 cfg80211_get_chandef_type(chandef))
17082 sme_config.csrConfig.channelBondingMode24GHz =
17083 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
17084 else
17085 sme_config.csrConfig.channelBondingMode24GHz =
17086 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
17087 sme_update_config(pHddCtx->hHal, &sme_config);
17088 cbModeChange = true;
17089 }
17090 break;
17091
17092 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017093 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017094 return -EINVAL;
17095 }
17096
17097 if (!cbModeChange)
17098 return 0;
17099
Krunal Sonib4326f22016-03-10 13:05:51 -080017100 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017101 return 0;
17102
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017103 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017104 sme_config.csrConfig.channelBondingMode24GHz);
17105
17106 /* Change SAP ht2040 mode */
17107 status = hdd_set_sap_ht2040_mode(pAdapter,
17108 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017109 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017110 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017111 return -EINVAL;
17112 }
17113
17114 return 0;
17115}
17116
17117/**
17118 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
17119 * @wiphy: Pointer to wiphy
17120 * @dev: Pointer to network device
17121 * @chandef: Pointer to channel definition parameter
17122 *
17123 * Return: 0 for success, non-zero for failure
17124 */
17125static int
17126wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
17127 struct net_device *dev,
17128 struct cfg80211_chan_def *chandef)
17129{
17130 int ret;
17131
17132 cds_ssr_protect(__func__);
17133 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
17134 cds_ssr_unprotect(__func__);
17135
17136 return ret;
17137}
17138#endif
17139
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017140#ifdef CHANNEL_SWITCH_SUPPORTED
17141/**
17142 * __wlan_hdd_cfg80211_channel_switch()- function to switch
17143 * channel in SAP/GO
17144 * @wiphy: wiphy pointer
17145 * @dev: dev pointer.
17146 * @csa_params: Change channel params
17147 *
17148 * This function is called to switch channel in SAP/GO
17149 *
17150 * Return: 0 if success else return non zero
17151 */
17152static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
17153 struct net_device *dev,
17154 struct cfg80211_csa_settings *csa_params)
17155{
17156 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
17157 hdd_context_t *hdd_ctx;
17158 uint8_t channel;
17159 uint16_t freq;
17160 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080017161 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017162
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017163 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017164 csa_params->chandef.chan->center_freq);
17165
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017166 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
17167 hdd_err("invalid session id: %d", adapter->sessionId);
17168 return -EINVAL;
17169 }
17170
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017171 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17172 ret = wlan_hdd_validate_context(hdd_ctx);
17173
17174 if (0 != ret)
17175 return ret;
17176
Krunal Sonib4326f22016-03-10 13:05:51 -080017177 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
17178 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017179 return -ENOTSUPP;
17180
17181 freq = csa_params->chandef.chan->center_freq;
17182 channel = cds_freq_to_chan(freq);
17183
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053017184 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
17185
17186 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017187 return ret;
17188}
17189
17190/**
17191 * wlan_hdd_cfg80211_channel_switch()- function to switch
17192 * channel in SAP/GO
17193 * @wiphy: wiphy pointer
17194 * @dev: dev pointer.
17195 * @csa_params: Change channel params
17196 *
17197 * This function is called to switch channel in SAP/GO
17198 *
17199 * Return: 0 if success else return non zero
17200 */
17201static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
17202 struct net_device *dev,
17203 struct cfg80211_csa_settings *csa_params)
17204{
17205 int ret;
17206
17207 cds_ssr_protect(__func__);
17208 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
17209 cds_ssr_unprotect(__func__);
17210 return ret;
17211}
17212#endif
17213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017214/**
17215 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
17216 * translation from NL to policy manager type
17217 * @type: Generic connection mode type defined in NL
17218 *
17219 *
17220 * This function provides the type translation
17221 *
17222 * Return: cds_con_mode enum
17223 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017224enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017225 enum nl80211_iftype type)
17226{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017227 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017228 switch (type) {
17229 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017230 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017231 break;
17232 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017233 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017234 break;
17235 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017236 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017237 break;
17238 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017239 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017240 break;
17241 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017242 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017243 break;
17244 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017245 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017246 }
17247 return mode;
17248}
17249
17250/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017251 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17252 * @wiphy: Handle to struct wiphy to get handle to module context.
17253 * @chandef: Contains information about the capture channel to be set.
17254 *
17255 * This interface is called if and only if monitor mode interface alone is
17256 * active.
17257 *
17258 * Return: 0 success or error code on failure.
17259 */
17260static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17261 struct cfg80211_chan_def *chandef)
17262{
17263 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
17264 hdd_adapter_t *adapter;
17265 hdd_station_ctx_t *sta_ctx;
17266 struct hdd_mon_set_ch_info *ch_info;
17267 QDF_STATUS status;
17268 tHalHandle hal_hdl;
17269 struct qdf_mac_addr bssid;
17270 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080017271 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017272 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017273 int ret;
17274 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
17275
17276 ENTER();
17277
17278 ret = wlan_hdd_validate_context(hdd_ctx);
17279 if (ret)
17280 return ret;
17281
17282 hal_hdl = hdd_ctx->hHal;
17283
17284 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
17285 if (!adapter)
17286 return -EIO;
17287
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017288 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017289 adapter->dev->name, chan_num, chandef->chan->center_freq);
17290
17291 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17292 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017293 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
17294 roam_profile.ChannelInfo.numOfChannels = 1;
17295 roam_profile.phyMode = ch_info->phy_mode;
17296 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017297 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017298
17299 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
17300 QDF_MAC_ADDR_SIZE);
17301
17302 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017303 /*
17304 * CDS api expects secondary channel for calculating
17305 * the channel params
17306 */
17307 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017308 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017309 if (chan_num >= 1 && chan_num <= 5)
17310 sec_ch = chan_num + 4;
17311 else if (chan_num >= 6 && chan_num <= 13)
17312 sec_ch = chan_num - 4;
17313 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017314 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
17315 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017316 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
17317 &roam_profile);
17318 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017319 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017320 status);
17321 ret = qdf_status_to_os_return(status);
17322 return ret;
17323 }
17324 EXIT();
17325 return 0;
17326}
17327
17328/**
17329 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17330 * @wiphy: Handle to struct wiphy to get handle to module context.
17331 * @chandef: Contains information about the capture channel to be set.
17332 *
17333 * This interface is called if and only if monitor mode interface alone is
17334 * active.
17335 *
17336 * Return: 0 success or error code on failure.
17337 */
17338static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17339 struct cfg80211_chan_def *chandef)
17340{
17341 int ret;
17342
17343 cds_ssr_protect(__func__);
17344 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
17345 cds_ssr_unprotect(__func__);
17346 return ret;
17347}
17348
17349/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017350 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
17351 * @adapter: pointer to adapter
17352 *
17353 * Wrapper function to clear link layer stats.
17354 * return - void
17355 */
17356void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
17357{
17358 tSirLLStatsClearReq link_layer_stats_clear_req;
17359 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
17360
Mukul Sharma491021c2016-09-29 21:39:19 +053017361 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
17362 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017363 link_layer_stats_clear_req.stopReq = 0;
17364 link_layer_stats_clear_req.reqId = 1;
17365 link_layer_stats_clear_req.staId = adapter->sessionId;
17366 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
17367
17368 return;
17369}
17370
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017371/**
17372 * hdd_process_defer_disconnect() - Handle the deferred disconnect
17373 * @adapter: HDD Adapter
17374 *
17375 * If roaming is in progress and there is a request to
17376 * disconnect the session, then it is deferred. Once
17377 * roaming is complete/aborted, then this routine is
17378 * used to resume the disconnect that was deferred
17379 *
17380 * Return: None
17381 */
17382void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
17383{
17384 switch (adapter->defer_disconnect) {
17385 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
17386 adapter->defer_disconnect = 0;
17387 wlan_hdd_disconnect(adapter,
17388 adapter->cfg80211_disconnect_reason);
17389 break;
17390 case DEFER_DISCONNECT_TRY_DISCONNECT:
17391 wlan_hdd_try_disconnect(adapter);
17392 adapter->defer_disconnect = 0;
17393 break;
17394 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017395 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017396 adapter->defer_disconnect);
17397 break;
17398 }
17399}
17400
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017401#define CNT_DIFF(cur, prev) \
17402 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
17403#define MAX_COUNT 0xffffffff
17404static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
17405 struct scan_chan_info *chan,
17406 struct scan_chan_info *info, uint32_t cmd_flag)
17407{
17408 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
17409 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
17410 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
17411
17412 mutex_lock(&hdd_ctx->chan_info_lock);
17413
17414 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
17415 qdf_mem_zero(chan, sizeof(*chan));
17416
17417 chan->freq = info->freq;
17418 chan->noise_floor = info->noise_floor;
17419 chan->clock_freq = info->clock_freq;
17420 chan->cmd_flag = info->cmd_flag;
17421 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
17422
17423 chan->rx_clear_count =
17424 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
17425
17426 chan->tx_frame_count =
17427 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
17428
17429 mutex_unlock(&hdd_ctx->chan_info_lock);
17430
17431}
17432#undef CNT_DIFF
17433#undef MAX_COUNT
17434
17435/**
17436 * wlan_hdd_chan_info_cb() - channel info callback
17437 * @chan_info: struct scan_chan_info
17438 *
17439 * Store channel info into HDD context
17440 *
17441 * Return: None.
17442 */
17443static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
17444{
17445 hdd_context_t *hdd_ctx;
17446 struct scan_chan_info *chan;
17447 uint8_t idx;
17448
17449 ENTER();
17450
17451 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17452 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
17453 hdd_err("hdd_ctx is invalid");
17454 return;
17455 }
17456
17457 if (!hdd_ctx->chan_info) {
17458 hdd_err("chan_info is NULL");
17459 return;
17460 }
17461
17462 chan = hdd_ctx->chan_info;
17463 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
17464 if (chan[idx].freq == info->freq) {
17465 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
17466 info->cmd_flag);
17467 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
17468 chan[idx].cmd_flag, chan[idx].freq,
17469 chan[idx].noise_floor,
17470 chan[idx].cycle_count, chan[idx].rx_clear_count,
17471 chan[idx].clock_freq, chan[idx].cmd_flag,
17472 chan[idx].tx_frame_count, idx);
17473 if (chan[idx].freq == 0)
17474 break;
17475
17476 }
17477 }
17478
17479 EXIT();
17480}
17481
17482/**
17483 * wlan_hdd_init_chan_info() - init chan info in hdd context
17484 * @hdd_ctx: HDD context pointer
17485 *
17486 * Return: none
17487 */
17488void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
17489{
17490 uint8_t num_2g, num_5g, index = 0;
17491
17492 if (!hdd_ctx->config->fEnableSNRMonitoring) {
17493 hdd_info("SNR monitoring is disabled");
17494 return;
17495 }
17496
17497 hdd_ctx->chan_info =
17498 qdf_mem_malloc(sizeof(struct scan_chan_info)
17499 * QDF_MAX_NUM_CHAN);
17500 if (hdd_ctx->chan_info == NULL) {
17501 hdd_err("Failed to malloc for chan info");
17502 return;
17503 }
17504 mutex_init(&hdd_ctx->chan_info_lock);
17505
17506 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
17507 for (; index < num_2g; index++) {
17508 hdd_ctx->chan_info[index].freq =
17509 hdd_channels_2_4_ghz[index].center_freq;
17510 }
17511
17512 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
17513 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017514 if (WLAN_REG_IS_11P_CH(
17515 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017516 continue;
17517 hdd_ctx->chan_info[index].freq =
17518 hdd_channels_5_ghz[index - num_2g].center_freq;
17519 }
17520 sme_set_chan_info_callback(hdd_ctx->hHal,
17521 &wlan_hdd_chan_info_cb);
17522}
17523
17524/**
17525 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
17526 * @hdd_ctx: hdd context pointer
17527 *
17528 * Return: none
17529 */
17530void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
17531{
17532 struct scan_chan_info *chan;
17533
17534 chan = hdd_ctx->chan_info;
17535 hdd_ctx->chan_info = NULL;
17536 if (chan)
17537 qdf_mem_free(chan);
17538}
17539
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017540/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017541 * struct cfg80211_ops - cfg80211_ops
17542 *
17543 * @add_virtual_intf: Add virtual interface
17544 * @del_virtual_intf: Delete virtual interface
17545 * @change_virtual_intf: Change virtual interface
17546 * @change_station: Change station
17547 * @add_beacon: Add beacon in sap mode
17548 * @del_beacon: Delete beacon in sap mode
17549 * @set_beacon: Set beacon in sap mode
17550 * @start_ap: Start ap
17551 * @change_beacon: Change beacon
17552 * @stop_ap: Stop ap
17553 * @change_bss: Change bss
17554 * @add_key: Add key
17555 * @get_key: Get key
17556 * @del_key: Delete key
17557 * @set_default_key: Set default key
17558 * @set_channel: Set channel
17559 * @scan: Scan
17560 * @connect: Connect
17561 * @disconnect: Disconnect
17562 * @join_ibss = Join ibss
17563 * @leave_ibss = Leave ibss
17564 * @set_wiphy_params = Set wiphy params
17565 * @set_tx_power = Set tx power
17566 * @get_tx_power = get tx power
17567 * @remain_on_channel = Remain on channel
17568 * @cancel_remain_on_channel = Cancel remain on channel
17569 * @mgmt_tx = Tx management frame
17570 * @mgmt_tx_cancel_wait = Cancel management tx wait
17571 * @set_default_mgmt_key = Set default management key
17572 * @set_txq_params = Set tx queue parameters
17573 * @get_station = Get station
17574 * @set_power_mgmt = Set power management
17575 * @del_station = Delete station
17576 * @add_station = Add station
17577 * @set_pmksa = Set pmksa
17578 * @del_pmksa = Delete pmksa
17579 * @flush_pmksa = Flush pmksa
17580 * @update_ft_ies = Update FT IEs
17581 * @tdls_mgmt = Tdls management
17582 * @tdls_oper = Tdls operation
17583 * @set_rekey_data = Set rekey data
17584 * @sched_scan_start = Scheduled scan start
17585 * @sched_scan_stop = Scheduled scan stop
17586 * @resume = Resume wlan
17587 * @suspend = Suspend wlan
17588 * @set_mac_acl = Set mac acl
17589 * @testmode_cmd = Test mode command
17590 * @set_ap_chanwidth = Set AP channel bandwidth
17591 * @dump_survey = Dump survey
17592 * @key_mgmt_set_pmk = Set pmk key management
17593 */
17594static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17595 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17596 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17597 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17598 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017599 .start_ap = wlan_hdd_cfg80211_start_ap,
17600 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17601 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017602 .change_bss = wlan_hdd_cfg80211_change_bss,
17603 .add_key = wlan_hdd_cfg80211_add_key,
17604 .get_key = wlan_hdd_cfg80211_get_key,
17605 .del_key = wlan_hdd_cfg80211_del_key,
17606 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17607 .scan = wlan_hdd_cfg80211_scan,
17608 .connect = wlan_hdd_cfg80211_connect,
17609 .disconnect = wlan_hdd_cfg80211_disconnect,
17610 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17611 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17612 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17613 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17614 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17615 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17616 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17617 .mgmt_tx = wlan_hdd_mgmt_tx,
17618 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17619 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17620 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017621 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017622 .get_station = wlan_hdd_cfg80211_get_station,
17623 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17624 .del_station = wlan_hdd_cfg80211_del_station,
17625 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017626 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17627 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17628 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017629#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017630 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17631#endif
17632#ifdef FEATURE_WLAN_TDLS
17633 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17634 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17635#endif
17636#ifdef WLAN_FEATURE_GTK_OFFLOAD
17637 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17638#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17639#ifdef FEATURE_WLAN_SCAN_PNO
17640 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17641 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17642#endif /*FEATURE_WLAN_SCAN_PNO */
17643 .resume = wlan_hdd_cfg80211_resume_wlan,
17644 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17645 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17646#ifdef WLAN_NL80211_TESTMODE
17647 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17648#endif
17649#ifdef QCA_HT_2040_COEX
17650 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17651#endif
17652 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017653#ifdef CHANNEL_SWITCH_SUPPORTED
17654 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17655#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017656 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017657#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17658 defined(CFG80211_ABORT_SCAN)
17659 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17660#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017661};